Add MonadBaseControl IO instance and catch HttpException

This commit is contained in:
Aditya Manthramurthy 2017-01-17 17:59:14 +05:30
parent 7d7b81cbe3
commit 8be4f0a06f
5 changed files with 72 additions and 15 deletions

View File

@ -42,7 +42,9 @@ library
, http-client , http-client
, http-conduit , http-conduit
, http-types , http-types
, lifted-base
, memory , memory
, monad-control
, resourcet , resourcet
, text , text
, time , time
@ -92,7 +94,9 @@ test-suite minio-hs-test
, http-client , http-client
, http-conduit , http-conduit
, http-types , http-types
, lifted-base
, memory , memory
, monad-control
, resourcet , resourcet
, tasty , tasty
, tasty-hunit , tasty-hunit

View File

@ -23,6 +23,7 @@ import Lib.Prelude
import Network.Minio.Data import Network.Minio.Data
import Network.Minio.Data.Crypto import Network.Minio.Data.Crypto
import Network.Minio.Sign.V4 import Network.Minio.Sign.V4
import Network.Minio.Utils
-- runRequestDebug r mgr = do -- runRequestDebug r mgr = do
-- print $ "runRequestDebug" -- print $ "runRequestDebug"
@ -72,18 +73,12 @@ buildRequest ri = do
, NC.requestBody = rbody , NC.requestBody = rbody
} }
isFailureStatus :: Response body -> Bool
isFailureStatus resp = let s = HT.statusCode (NC.responseStatus resp)
in not (s >= 200 && s < 300)
executeRequest :: RequestInfo -> Minio (Response LByteString) executeRequest :: RequestInfo -> Minio (Response LByteString)
executeRequest ri = do executeRequest ri = do
req <- buildRequest ri req <- buildRequest ri
mgr <- asks mcConnManager mgr <- asks mcConnManager
resp <- NC.httpLbs req mgr httpLbs req mgr
if (isFailureStatus resp)
then throwError $ MErrService $ LBS.toStrict $ NC.responseBody resp
else return resp
mkStreamRequest :: RequestInfo mkStreamRequest :: RequestInfo
@ -91,11 +86,7 @@ mkStreamRequest :: RequestInfo
mkStreamRequest ri = do mkStreamRequest ri = do
req <- buildRequest ri req <- buildRequest ri
mgr <- asks mcConnManager mgr <- asks mcConnManager
resp <- NC.http req mgr http req mgr
if (isFailureStatus resp)
then do errResp <- NC.lbsResponse resp
throwError $ MErrService $ LBS.toStrict $ NC.responseBody errResp
else return resp
requestInfo :: Method -> Maybe Bucket -> Maybe Object requestInfo :: Method -> Maybe Bucket -> Maybe Object

View File

@ -1,4 +1,4 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies #-}
module Network.Minio.Data module Network.Minio.Data
( ConnectInfo(..) ( ConnectInfo(..)
, RequestInfo(..) , RequestInfo(..)
@ -24,8 +24,11 @@ import Network.HTTP.Client (defaultManagerSettings, HttpException)
import Network.HTTP.Types (Method, Header, Query) import Network.HTTP.Types (Method, Header, Query)
import qualified Network.HTTP.Conduit as NC import qualified Network.HTTP.Conduit as NC
import Control.Monad.Trans.Resource (MonadThrow, MonadResource, ResourceT) -- import Control.Monad.Trans.Resource (MonadThrow, MonadResource, ResourceT,
import Control.Monad.Base (MonadBase(..)) -- MonadBaseControl(..))
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Control
import Control.Monad.Base
import Text.XML import Text.XML
@ -108,6 +111,11 @@ newtype Minio a = Minio {
, MonadResource , MonadResource
) )
instance MonadBaseControl IO Minio where
type StM Minio a = Either MinioErr a
liftBaseWith f = Minio $ liftBaseWith $ \q -> f (q . unMinio)
restoreM = Minio . restoreM
-- MinioConn holds connection info and a connection pool -- MinioConn holds connection info and a connection pool
data MinioConn = MinioConn { data MinioConn = MinioConn {
mcConnInfo :: ConnectInfo mcConnInfo :: ConnectInfo

View File

@ -2,11 +2,24 @@ module Network.Minio.Utils where
import qualified Control.Monad.Trans.Resource as R import qualified Control.Monad.Trans.Resource as R
import qualified System.IO as IO import qualified System.IO as IO
import qualified Network.HTTP.Conduit as NC
import qualified Network.HTTP.Client as NClient
import Network.HTTP.Conduit (Response)
import qualified Data.Conduit as C
import qualified Data.ByteString.Lazy as LBS
import qualified Network.HTTP.Types as HT
import Control.Monad.Trans.Except (withExceptT, ExceptT(..), withExcept)
import Control.Monad.Base (MonadBase(..))
import qualified Control.Exception.Lifted as ExL
import Lib.Prelude import Lib.Prelude
import Network.Minio.Data import Network.Minio.Data
-- tryIO :: (MonadIO m, MonadError MinioErr m) => IO a -> m a
-- tryIO act = either (throwError . MErrIO) return $ try act
allocateReadFile :: (R.MonadResource m, MonadError MinioErr m) allocateReadFile :: (R.MonadResource m, MonadError MinioErr m)
=> FilePath -> m (R.ReleaseKey, Handle) => FilePath -> m (R.ReleaseKey, Handle)
allocateReadFile fp = do allocateReadFile fp = do
@ -15,3 +28,34 @@ allocateReadFile fp = do
where where
openReadFile f = runExceptT $ tryIO $ IO.openBinaryFile f IO.ReadMode openReadFile f = runExceptT $ tryIO $ IO.openBinaryFile f IO.ReadMode
cleanup = either (const $ return ()) IO.hClose cleanup = either (const $ return ()) IO.hClose
isSuccessStatus sts = let s = HT.statusCode sts
in (s >= 200 && s < 300)
checkEither :: (Monad m, MonadError MinioErr m)
=> (e -> MinioErr) -> (Either e a) -> m a
checkEither f = either (throwError . f) return
httpLbs :: (MonadError MinioErr m, MonadIO m)
=> NC.Request -> NC.Manager
-> m (NC.Response LByteString)
httpLbs req mgr = do
respE <- liftIO $ try $ NClient.httpLbs req mgr
resp <- checkEither MErrHttp respE
unless (isSuccessStatus $ NC.responseStatus resp) $
throwError $ MErrService $ LBS.toStrict $ NC.responseBody resp
return resp
-- http :: (MonadError MinioErr m, R.MonadResourceBase m, R.MonadResource m)
-- => NC.Request -> NC.Manager
-- -> m (Response (C.ResumableSource m ByteString))
http :: NC.Request -> NC.Manager
-> Minio (Response (C.ResumableSource Minio ByteString))
http req mgr = do
respE <- ExL.try $ NC.http req mgr
resp <- checkEither MErrHttp respE
unless (isSuccessStatus $ NC.responseStatus resp) $ do
lbsResp <- NC.lbsResponse resp
throwError $ MErrService $ LBS.toStrict $ NC.responseBody lbsResp
return resp

View File

@ -56,6 +56,16 @@ unitTests = testGroup "Unit tests"
step "Running test.." step "Running test.."
ret <- runResourceT $ runMinio mc $ getService ret <- runResourceT $ runMinio mc $ getService
isRight ret @? ("getService failure => " ++ show ret) isRight ret @? ("getService failure => " ++ show ret)
, testCaseSteps "Simple fGetObject works" $ \step -> do
step "Preparing..."
mc <- connect defaultConnectInfo
step "Running test.."
ret <- runResourceT $ runMinio mc $
fGetObject "testbucket" "lsb-release" "/tmp/out"
isRight ret @? ("fGetObject failure => " ++ show ret)
, testCaseSteps "Simple putObject works" $ \step -> do , testCaseSteps "Simple putObject works" $ \step -> do
step "Preparing..." step "Preparing..."