Drop dependency on exceptions lib (#87)
This commit is contained in:
parent
522d49452f
commit
d25c7ef1dc
@ -55,7 +55,6 @@ library
|
|||||||
, cryptonite
|
, cryptonite
|
||||||
, cryptonite-conduit
|
, cryptonite-conduit
|
||||||
, data-default
|
, data-default
|
||||||
, exceptions
|
|
||||||
, filepath
|
, filepath
|
||||||
, http-client
|
, http-client
|
||||||
, http-conduit
|
, http-conduit
|
||||||
@ -137,7 +136,6 @@ test-suite minio-hs-live-server-test
|
|||||||
, cryptonite-conduit
|
, cryptonite-conduit
|
||||||
, data-default
|
, data-default
|
||||||
, directory
|
, directory
|
||||||
, exceptions
|
|
||||||
, filepath
|
, filepath
|
||||||
, http-client
|
, http-client
|
||||||
, http-conduit
|
, http-conduit
|
||||||
@ -177,7 +175,6 @@ test-suite minio-hs-test
|
|||||||
, cryptonite-conduit
|
, cryptonite-conduit
|
||||||
, data-default
|
, data-default
|
||||||
, directory
|
, directory
|
||||||
, exceptions
|
|
||||||
, http-client
|
, http-client
|
||||||
, http-conduit
|
, http-conduit
|
||||||
, http-types
|
, http-types
|
||||||
|
|||||||
@ -19,14 +19,14 @@ module Lib.Prelude
|
|||||||
, both
|
, both
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Protolude as Exports
|
import Protolude as Exports hiding (catch, catches,
|
||||||
|
throwIO, try)
|
||||||
|
|
||||||
import Control.Monad.Trans.Maybe as Exports (MaybeT (..), runMaybeT)
|
import Control.Monad.Trans.Maybe as Exports (MaybeT (..), runMaybeT)
|
||||||
import Data.Time as Exports (UTCTime (..),
|
import Data.Time as Exports (UTCTime (..),
|
||||||
diffUTCTime)
|
diffUTCTime)
|
||||||
|
import UnliftIO as Exports (catch, catches, throwIO,
|
||||||
import Control.Monad.Catch as Exports (MonadCatch, MonadThrow,
|
try)
|
||||||
throwM)
|
|
||||||
|
|
||||||
-- | Apply a function on both elements of a pair
|
-- | Apply a function on both elements of a pair
|
||||||
both :: (a -> b) -> (a, a) -> (b, b)
|
both :: (a -> b) -> (a, a) -> (b, b)
|
||||||
|
|||||||
@ -116,7 +116,7 @@ buildRequest ri = do
|
|||||||
Nothing -> return $ connectHost ci
|
Nothing -> return $ connectHost ci
|
||||||
Just r -> if "amazonaws.com" `T.isSuffixOf` connectHost ci
|
Just r -> if "amazonaws.com" `T.isSuffixOf` connectHost ci
|
||||||
then maybe
|
then maybe
|
||||||
(throwM $ MErrVRegionNotSupported r)
|
(throwIO $ MErrVRegionNotSupported r)
|
||||||
return
|
return
|
||||||
(Map.lookup r awsRegionMap)
|
(Map.lookup r awsRegionMap)
|
||||||
else return $ connectHost ci
|
else return $ connectHost ci
|
||||||
@ -192,16 +192,16 @@ isValidBucketName bucket =
|
|||||||
isIPCheck = and labelAsNums && length labelAsNums == 4
|
isIPCheck = and labelAsNums && length labelAsNums == 4
|
||||||
|
|
||||||
-- Throws exception iff bucket name is invalid according to AWS rules.
|
-- Throws exception iff bucket name is invalid according to AWS rules.
|
||||||
checkBucketNameValidity :: MonadThrow m => Bucket -> m ()
|
checkBucketNameValidity :: MonadIO m => Bucket -> m ()
|
||||||
checkBucketNameValidity bucket =
|
checkBucketNameValidity bucket =
|
||||||
when (not $ isValidBucketName bucket) $
|
when (not $ isValidBucketName bucket) $
|
||||||
throwM $ MErrVInvalidBucketName bucket
|
throwIO $ MErrVInvalidBucketName bucket
|
||||||
|
|
||||||
isValidObjectName :: Object -> Bool
|
isValidObjectName :: Object -> Bool
|
||||||
isValidObjectName object =
|
isValidObjectName object =
|
||||||
T.length object > 0 && B.length (encodeUtf8 object) <= 1024
|
T.length object > 0 && B.length (encodeUtf8 object) <= 1024
|
||||||
|
|
||||||
checkObjectNameValidity :: MonadThrow m => Object -> m ()
|
checkObjectNameValidity :: MonadIO m => Object -> m ()
|
||||||
checkObjectNameValidity object =
|
checkObjectNameValidity object =
|
||||||
when (not $ isValidObjectName object) $
|
when (not $ isValidObjectName object) $
|
||||||
throwM $ MErrVInvalidObjectName object
|
throwIO $ MErrVInvalidObjectName object
|
||||||
|
|||||||
@ -47,7 +47,7 @@ copyObjectInternal b' o srcInfo = do
|
|||||||
when (isJust rangeMay &&
|
when (isJust rangeMay &&
|
||||||
or [startOffset < 0, endOffset < startOffset,
|
or [startOffset < 0, endOffset < startOffset,
|
||||||
endOffset >= fromIntegral srcSize]) $
|
endOffset >= fromIntegral srcSize]) $
|
||||||
throwM $ MErrVInvalidSrcObjByteRange range
|
throwIO $ MErrVInvalidSrcObjByteRange range
|
||||||
|
|
||||||
-- 1. If sz > 64MiB (minPartSize) use multipart copy, OR
|
-- 1. If sz > 64MiB (minPartSize) use multipart copy, OR
|
||||||
-- 2. If startOffset /= 0 use multipart copy
|
-- 2. If startOffset /= 0 use multipart copy
|
||||||
|
|||||||
@ -20,7 +20,6 @@ module Network.Minio.Data where
|
|||||||
|
|
||||||
import Control.Concurrent.MVar (MVar)
|
import Control.Concurrent.MVar (MVar)
|
||||||
import qualified Control.Concurrent.MVar as M
|
import qualified Control.Concurrent.MVar as M
|
||||||
import qualified Control.Monad.Catch as MC
|
|
||||||
import Control.Monad.IO.Unlift (MonadUnliftIO, UnliftIO (..),
|
import Control.Monad.IO.Unlift (MonadUnliftIO, UnliftIO (..),
|
||||||
askUnliftIO, withUnliftIO)
|
askUnliftIO, withUnliftIO)
|
||||||
import Control.Monad.Trans.Resource
|
import Control.Monad.Trans.Resource
|
||||||
@ -38,6 +37,7 @@ import Network.HTTP.Types (ByteRange, Header, Method, Query,
|
|||||||
import qualified Network.HTTP.Types as HT
|
import qualified Network.HTTP.Types as HT
|
||||||
import Network.Minio.Errors
|
import Network.Minio.Errors
|
||||||
import Text.XML
|
import Text.XML
|
||||||
|
import qualified UnliftIO as U
|
||||||
|
|
||||||
import Lib.Prelude
|
import Lib.Prelude
|
||||||
|
|
||||||
@ -102,7 +102,6 @@ getHostAddr ci = toS $ T.concat [ connectHost ci, ":"
|
|||||||
, Lib.Prelude.show $ connectPort ci
|
, Lib.Prelude.show $ connectPort ci
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
-- | Default AWS ConnectInfo. Connects to "us-east-1". Credentials
|
-- | Default AWS ConnectInfo. Connects to "us-east-1". Credentials
|
||||||
-- should be supplied before use, for e.g.:
|
-- should be supplied before use, for e.g.:
|
||||||
--
|
--
|
||||||
@ -512,8 +511,6 @@ newtype Minio a = Minio {
|
|||||||
, Monad
|
, Monad
|
||||||
, MonadIO
|
, MonadIO
|
||||||
, MonadReader MinioConn
|
, MonadReader MinioConn
|
||||||
, MonadThrow
|
|
||||||
, MonadCatch
|
|
||||||
, MonadResource
|
, MonadResource
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -544,11 +541,11 @@ runMinio :: ConnectInfo -> Minio a -> IO (Either MinioErr a)
|
|||||||
runMinio ci m = do
|
runMinio ci m = do
|
||||||
conn <- liftIO $ connect ci
|
conn <- liftIO $ connect ci
|
||||||
runResourceT . flip runReaderT conn . unMinio $
|
runResourceT . flip runReaderT conn . unMinio $
|
||||||
fmap Right m `MC.catches`
|
fmap Right m `U.catches`
|
||||||
[ MC.Handler handlerServiceErr
|
[ U.Handler handlerServiceErr
|
||||||
, MC.Handler handlerHE
|
, U.Handler handlerHE
|
||||||
, MC.Handler handlerFE
|
, U.Handler handlerFE
|
||||||
, MC.Handler handlerValidation
|
, U.Handler handlerValidation
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
handlerServiceErr = return . Left . MErrService
|
handlerServiceErr = return . Left . MErrService
|
||||||
|
|||||||
@ -66,7 +66,7 @@ makePresignedUrl :: UrlExpiry -> HT.Method -> Maybe Bucket -> Maybe Object
|
|||||||
-> Minio ByteString
|
-> Minio ByteString
|
||||||
makePresignedUrl expiry method bucket object region extraQuery extraHeaders = do
|
makePresignedUrl expiry method bucket object region extraQuery extraHeaders = do
|
||||||
when (expiry > 7*24*3600 || expiry < 0) $
|
when (expiry > 7*24*3600 || expiry < 0) $
|
||||||
throwM $ MErrVInvalidUrlExpiry expiry
|
throwIO $ MErrVInvalidUrlExpiry expiry
|
||||||
|
|
||||||
ci <- asks mcConnInfo
|
ci <- asks mcConnInfo
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ putObjectInternal b o opts (ODStream src sizeMay) = do
|
|||||||
if | size <= 64 * oneMiB -> do
|
if | size <= 64 * oneMiB -> do
|
||||||
bs <- C.runConduit $ src C..| CB.sinkLbs
|
bs <- C.runConduit $ src C..| CB.sinkLbs
|
||||||
putObjectSingle' b o (pooToHeaders opts) $ LBS.toStrict bs
|
putObjectSingle' b o (pooToHeaders opts) $ LBS.toStrict bs
|
||||||
| size > maxObjectSize -> throwM $ MErrVPutSizeExceeded size
|
| size > maxObjectSize -> throwIO $ MErrVPutSizeExceeded size
|
||||||
| otherwise -> sequentialMultipartUpload b o opts (Just size) src
|
| otherwise -> sequentialMultipartUpload b o opts (Just size) src
|
||||||
|
|
||||||
putObjectInternal b o opts (ODFile fp sizeMay) = do
|
putObjectInternal b o opts (ODFile fp sizeMay) = do
|
||||||
@ -90,9 +90,9 @@ putObjectInternal b o opts (ODFile fp sizeMay) = do
|
|||||||
|
|
||||||
-- got file size, so check for single/multipart upload
|
-- got file size, so check for single/multipart upload
|
||||||
Just size ->
|
Just size ->
|
||||||
if | size <= 64 * oneMiB -> either throwM return =<<
|
if | size <= 64 * oneMiB -> either throwIO return =<<
|
||||||
withNewHandle fp (\h -> putObjectSingle b o (pooToHeaders opts) h 0 size)
|
withNewHandle fp (\h -> putObjectSingle b o (pooToHeaders opts) h 0 size)
|
||||||
| size > maxObjectSize -> throwM $ MErrVPutSizeExceeded size
|
| size > maxObjectSize -> throwIO $ MErrVPutSizeExceeded size
|
||||||
| isSeekable -> parallelMultipartUpload b o opts fp size
|
| isSeekable -> parallelMultipartUpload b o opts fp size
|
||||||
| otherwise -> sequentialMultipartUpload b o opts (Just size) $
|
| otherwise -> sequentialMultipartUpload b o opts (Just size) $
|
||||||
CB.sourceFile fp
|
CB.sourceFile fp
|
||||||
@ -112,7 +112,7 @@ parallelMultipartUpload b o opts filePath size = do
|
|||||||
(uploadPart uploadId) partSizeInfo
|
(uploadPart uploadId) partSizeInfo
|
||||||
|
|
||||||
-- if there were any errors, rethrow exception.
|
-- if there were any errors, rethrow exception.
|
||||||
mapM_ throwM $ lefts uploadedPartsE
|
mapM_ throwIO $ lefts uploadedPartsE
|
||||||
|
|
||||||
-- if we get here, all parts were successfully uploaded.
|
-- if we get here, all parts were successfully uploaded.
|
||||||
completeMultipartUpload b o uploadId $ rights uploadedPartsE
|
completeMultipartUpload b o uploadId $ rights uploadedPartsE
|
||||||
|
|||||||
@ -90,16 +90,16 @@ module Network.Minio.S3API
|
|||||||
, removeAllBucketNotification
|
, removeAllBucketNotification
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Catch (Handler (..), catches)
|
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.Conduit as C
|
import qualified Data.Conduit as C
|
||||||
import Data.Default (def)
|
import Data.Default (def)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
import Lib.Prelude hiding (catches)
|
|
||||||
import qualified Network.HTTP.Conduit as NC
|
import qualified Network.HTTP.Conduit as NC
|
||||||
import qualified Network.HTTP.Types as HT
|
import qualified Network.HTTP.Types as HT
|
||||||
import Network.HTTP.Types.Status (status404)
|
import Network.HTTP.Types.Status (status404)
|
||||||
|
import UnliftIO (Handler (Handler))
|
||||||
|
|
||||||
|
import Lib.Prelude
|
||||||
|
|
||||||
import Network.Minio.API
|
import Network.Minio.API
|
||||||
import Network.Minio.Data
|
import Network.Minio.Data
|
||||||
@ -150,7 +150,7 @@ putObjectSingle' bucket object headers bs = do
|
|||||||
let size = fromIntegral (BS.length bs)
|
let size = fromIntegral (BS.length bs)
|
||||||
-- check length is within single PUT object size.
|
-- check length is within single PUT object size.
|
||||||
when (size > maxSinglePutObjectSizeBytes) $
|
when (size > maxSinglePutObjectSizeBytes) $
|
||||||
throwM $ MErrVSinglePUTSizeExceeded size
|
throwIO $ MErrVSinglePUTSizeExceeded size
|
||||||
|
|
||||||
-- content-length header is automatically set by library.
|
-- content-length header is automatically set by library.
|
||||||
resp <- executeRequest $
|
resp <- executeRequest $
|
||||||
@ -164,7 +164,7 @@ putObjectSingle' bucket object headers bs = do
|
|||||||
let rheaders = NC.responseHeaders resp
|
let rheaders = NC.responseHeaders resp
|
||||||
etag = getETagHeader rheaders
|
etag = getETagHeader rheaders
|
||||||
maybe
|
maybe
|
||||||
(throwM MErrVETagHeaderNotFound)
|
(throwIO MErrVETagHeaderNotFound)
|
||||||
return etag
|
return etag
|
||||||
|
|
||||||
-- | PUT an object into the service. This function performs a single
|
-- | PUT an object into the service. This function performs a single
|
||||||
@ -174,7 +174,7 @@ putObjectSingle :: Bucket -> Object -> [HT.Header] -> Handle -> Int64
|
|||||||
putObjectSingle bucket object headers h offset size = do
|
putObjectSingle bucket object headers h offset size = do
|
||||||
-- check length is within single PUT object size.
|
-- check length is within single PUT object size.
|
||||||
when (size > maxSinglePutObjectSizeBytes) $
|
when (size > maxSinglePutObjectSizeBytes) $
|
||||||
throwM $ MErrVSinglePUTSizeExceeded size
|
throwIO $ MErrVSinglePUTSizeExceeded size
|
||||||
|
|
||||||
-- content-length header is automatically set by library.
|
-- content-length header is automatically set by library.
|
||||||
resp <- executeRequest $
|
resp <- executeRequest $
|
||||||
@ -188,7 +188,7 @@ putObjectSingle bucket object headers h offset size = do
|
|||||||
let rheaders = NC.responseHeaders resp
|
let rheaders = NC.responseHeaders resp
|
||||||
etag = getETagHeader rheaders
|
etag = getETagHeader rheaders
|
||||||
maybe
|
maybe
|
||||||
(throwM MErrVETagHeaderNotFound)
|
(throwIO MErrVETagHeaderNotFound)
|
||||||
return etag
|
return etag
|
||||||
|
|
||||||
-- | List objects in a bucket matching prefix up to delimiter,
|
-- | List objects in a bucket matching prefix up to delimiter,
|
||||||
@ -271,7 +271,7 @@ putObjectPart bucket object uploadId partNumber headers payload = do
|
|||||||
let rheaders = NC.responseHeaders resp
|
let rheaders = NC.responseHeaders resp
|
||||||
etag = getETagHeader rheaders
|
etag = getETagHeader rheaders
|
||||||
maybe
|
maybe
|
||||||
(throwM MErrVETagHeaderNotFound)
|
(throwIO MErrVETagHeaderNotFound)
|
||||||
(return . (partNumber, )) etag
|
(return . (partNumber, )) etag
|
||||||
where
|
where
|
||||||
params = [
|
params = [
|
||||||
@ -325,7 +325,7 @@ copyObjectSingle :: Bucket -> Object -> SourceInfo -> [HT.Header]
|
|||||||
copyObjectSingle bucket object srcInfo headers = do
|
copyObjectSingle bucket object srcInfo headers = do
|
||||||
-- validate that srcRange is Nothing for this API.
|
-- validate that srcRange is Nothing for this API.
|
||||||
when (isJust $ srcRange srcInfo) $
|
when (isJust $ srcRange srcInfo) $
|
||||||
throwM MErrVCopyObjSingleNoRangeAccepted
|
throwIO MErrVCopyObjSingleNoRangeAccepted
|
||||||
resp <- executeRequest $
|
resp <- executeRequest $
|
||||||
def { riMethod = HT.methodPut
|
def { riMethod = HT.methodPut
|
||||||
, riBucket = Just bucket
|
, riBucket = Just bucket
|
||||||
@ -414,7 +414,7 @@ headObject bucket object = do
|
|||||||
size = getContentLength headers
|
size = getContentLength headers
|
||||||
metadata = getMetadataMap headers
|
metadata = getMetadataMap headers
|
||||||
|
|
||||||
maybe (throwM MErrVInvalidObjectInfoResponse) return $
|
maybe (throwIO MErrVInvalidObjectInfoResponse) return $
|
||||||
ObjectInfo <$> Just object <*> modTime <*> etag <*> size <*> Just metadata
|
ObjectInfo <$> Just object <*> modTime <*> etag <*> size <*> Just metadata
|
||||||
|
|
||||||
|
|
||||||
@ -428,14 +428,14 @@ headBucket bucket = headBucketEx `catches`
|
|||||||
where
|
where
|
||||||
handleNoSuchBucket :: ServiceErr -> Minio Bool
|
handleNoSuchBucket :: ServiceErr -> Minio Bool
|
||||||
handleNoSuchBucket e | e == NoSuchBucket = return False
|
handleNoSuchBucket e | e == NoSuchBucket = return False
|
||||||
| otherwise = throwM e
|
| otherwise = throwIO e
|
||||||
|
|
||||||
handleStatus404 :: NC.HttpException -> Minio Bool
|
handleStatus404 :: NC.HttpException -> Minio Bool
|
||||||
handleStatus404 e@(NC.HttpExceptionRequest _ (NC.StatusCodeException res _)) =
|
handleStatus404 e@(NC.HttpExceptionRequest _ (NC.StatusCodeException res _)) =
|
||||||
if NC.responseStatus res == status404
|
if NC.responseStatus res == status404
|
||||||
then return False
|
then return False
|
||||||
else throwM e
|
else throwIO e
|
||||||
handleStatus404 e = throwM e
|
handleStatus404 e = throwIO e
|
||||||
|
|
||||||
headBucketEx = do
|
headBucketEx = do
|
||||||
resp <- executeRequest $ def { riMethod = HT.methodHead
|
resp <- executeRequest $ def { riMethod = HT.methodHead
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
module Network.Minio.Utils where
|
module Network.Minio.Utils where
|
||||||
|
|
||||||
import qualified Control.Monad.Catch as MC
|
|
||||||
import Control.Monad.IO.Unlift (MonadUnliftIO)
|
import Control.Monad.IO.Unlift (MonadUnliftIO)
|
||||||
import qualified Control.Monad.Trans.Resource as R
|
import qualified Control.Monad.Trans.Resource as R
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
@ -36,10 +35,9 @@ import qualified Network.HTTP.Conduit as NC
|
|||||||
import qualified Network.HTTP.Types as HT
|
import qualified Network.HTTP.Types as HT
|
||||||
import qualified Network.HTTP.Types.Header as Hdr
|
import qualified Network.HTTP.Types.Header as Hdr
|
||||||
import qualified System.IO as IO
|
import qualified System.IO as IO
|
||||||
|
import qualified UnliftIO as U
|
||||||
import qualified UnliftIO.Async as A
|
import qualified UnliftIO.Async as A
|
||||||
import qualified UnliftIO.Exception as UEx
|
|
||||||
import qualified UnliftIO.MVar as UM
|
import qualified UnliftIO.MVar as UM
|
||||||
import qualified UnliftIO.STM as U
|
|
||||||
|
|
||||||
import Lib.Prelude
|
import Lib.Prelude
|
||||||
|
|
||||||
@ -47,13 +45,13 @@ import Network.Minio.Data
|
|||||||
import Network.Minio.Data.ByteString
|
import Network.Minio.Data.ByteString
|
||||||
import Network.Minio.XmlParser (parseErrResponse)
|
import Network.Minio.XmlParser (parseErrResponse)
|
||||||
|
|
||||||
allocateReadFile :: (MonadUnliftIO m, R.MonadResource m, MonadCatch m)
|
allocateReadFile :: (MonadUnliftIO m, R.MonadResource m)
|
||||||
=> FilePath -> m (R.ReleaseKey, Handle)
|
=> FilePath -> m (R.ReleaseKey, Handle)
|
||||||
allocateReadFile fp = do
|
allocateReadFile fp = do
|
||||||
(rk, hdlE) <- R.allocate (openReadFile fp) cleanup
|
(rk, hdlE) <- R.allocate (openReadFile fp) cleanup
|
||||||
either (\(e :: IOException) -> throwM e) (return . (rk,)) hdlE
|
either (\(e :: IOException) -> throwIO e) (return . (rk,)) hdlE
|
||||||
where
|
where
|
||||||
openReadFile f = UEx.try $ IO.openBinaryFile f IO.ReadMode
|
openReadFile f = U.try $ IO.openBinaryFile f IO.ReadMode
|
||||||
cleanup = either (const $ return ()) IO.hClose
|
cleanup = either (const $ return ()) IO.hClose
|
||||||
|
|
||||||
-- | Queries the file size from the handle. Catches any file operation
|
-- | Queries the file size from the handle. Catches any file operation
|
||||||
@ -80,17 +78,17 @@ isHandleSeekable h = do
|
|||||||
-- the given action on it. Exceptions of type MError are caught and
|
-- the given action on it. Exceptions of type MError are caught and
|
||||||
-- returned - both during file handle allocation and when the action
|
-- returned - both during file handle allocation and when the action
|
||||||
-- is run.
|
-- is run.
|
||||||
withNewHandle :: (MonadUnliftIO m, R.MonadResource m, MonadCatch m)
|
withNewHandle :: (MonadUnliftIO m, R.MonadResource m)
|
||||||
=> FilePath -> (Handle -> m a) -> m (Either IOException a)
|
=> FilePath -> (Handle -> m a) -> m (Either IOException a)
|
||||||
withNewHandle fp fileAction = do
|
withNewHandle fp fileAction = do
|
||||||
-- opening a handle can throw MError exception.
|
-- opening a handle can throw MError exception.
|
||||||
handleE <- MC.try $ allocateReadFile fp
|
handleE <- try $ allocateReadFile fp
|
||||||
either (return . Left) doAction handleE
|
either (return . Left) doAction handleE
|
||||||
where
|
where
|
||||||
doAction (rkey, h) = do
|
doAction (rkey, h) = do
|
||||||
-- fileAction may also throw MError exception, so we catch and
|
-- fileAction may also throw MError exception, so we catch and
|
||||||
-- return it.
|
-- return it.
|
||||||
resE <- MC.try $ fileAction h
|
resE <- try $ fileAction h
|
||||||
R.release rkey
|
R.release rkey
|
||||||
return resE
|
return resE
|
||||||
|
|
||||||
@ -127,19 +125,19 @@ isSuccessStatus :: HT.Status -> Bool
|
|||||||
isSuccessStatus sts = let s = HT.statusCode sts
|
isSuccessStatus sts = let s = HT.statusCode sts
|
||||||
in (s >= 200 && s < 300)
|
in (s >= 200 && s < 300)
|
||||||
|
|
||||||
httpLbs :: (R.MonadThrow m, MonadIO m)
|
httpLbs :: MonadIO m
|
||||||
=> NC.Request -> NC.Manager
|
=> NC.Request -> NC.Manager
|
||||||
-> m (NC.Response LByteString)
|
-> m (NC.Response LByteString)
|
||||||
httpLbs req mgr = do
|
httpLbs req mgr = do
|
||||||
respE <- liftIO $ tryHttpEx $ NC.httpLbs req mgr
|
respE <- liftIO $ tryHttpEx $ NC.httpLbs req mgr
|
||||||
resp <- either throwM return respE
|
resp <- either throwIO return respE
|
||||||
unless (isSuccessStatus $ NC.responseStatus resp) $
|
unless (isSuccessStatus $ NC.responseStatus resp) $
|
||||||
case contentTypeMay resp of
|
case contentTypeMay resp of
|
||||||
Just "application/xml" -> do
|
Just "application/xml" -> do
|
||||||
sErr <- parseErrResponse $ NC.responseBody resp
|
sErr <- parseErrResponse $ NC.responseBody resp
|
||||||
throwM sErr
|
throwIO sErr
|
||||||
|
|
||||||
_ -> throwM $ NC.HttpExceptionRequest req $
|
_ -> throwIO $ NC.HttpExceptionRequest req $
|
||||||
NC.StatusCodeException (void resp) (show resp)
|
NC.StatusCodeException (void resp) (show resp)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
@ -150,23 +148,22 @@ httpLbs req mgr = do
|
|||||||
contentTypeMay resp = lookupHeader Hdr.hContentType $
|
contentTypeMay resp = lookupHeader Hdr.hContentType $
|
||||||
NC.responseHeaders resp
|
NC.responseHeaders resp
|
||||||
|
|
||||||
http :: (MonadUnliftIO m, MonadThrow m, R.MonadResource m)
|
http :: (MonadUnliftIO m, R.MonadResource m)
|
||||||
=> NC.Request -> NC.Manager
|
=> NC.Request -> NC.Manager
|
||||||
-> m (Response (C.ConduitT () ByteString m ()))
|
-> m (Response (C.ConduitT () ByteString m ()))
|
||||||
http req mgr = do
|
http req mgr = do
|
||||||
respE <- tryHttpEx $ NC.http req mgr
|
respE <- tryHttpEx $ NC.http req mgr
|
||||||
resp <- either throwM return respE
|
resp <- either throwIO return respE
|
||||||
unless (isSuccessStatus $ NC.responseStatus resp) $
|
unless (isSuccessStatus $ NC.responseStatus resp) $
|
||||||
case contentTypeMay resp of
|
case contentTypeMay resp of
|
||||||
Just "application/xml" -> do
|
Just "application/xml" -> do
|
||||||
respBody <- C.connect (NC.responseBody resp) CB.sinkLbs
|
respBody <- C.connect (NC.responseBody resp) CB.sinkLbs
|
||||||
--respBody <- C.unsealConduitT (NC.responseBody resp) C.$$+- CB.sinkLbs
|
|
||||||
sErr <- parseErrResponse respBody
|
sErr <- parseErrResponse respBody
|
||||||
throwM sErr
|
throwIO sErr
|
||||||
|
|
||||||
_ -> do
|
_ -> do
|
||||||
content <- LB.toStrict . NC.responseBody <$> NC.lbsResponse resp
|
content <- LB.toStrict . NC.responseBody <$> NC.lbsResponse resp
|
||||||
throwM $ NC.HttpExceptionRequest req $
|
throwIO $ NC.HttpExceptionRequest req $
|
||||||
NC.StatusCodeException (void resp) content
|
NC.StatusCodeException (void resp) content
|
||||||
|
|
||||||
|
|
||||||
@ -174,8 +171,9 @@ http req mgr = do
|
|||||||
where
|
where
|
||||||
tryHttpEx :: (MonadUnliftIO m) => m a
|
tryHttpEx :: (MonadUnliftIO m) => m a
|
||||||
-> m (Either NC.HttpException a)
|
-> m (Either NC.HttpException a)
|
||||||
tryHttpEx = UEx.try
|
tryHttpEx = try
|
||||||
contentTypeMay resp = lookupHeader Hdr.hContentType $ NC.responseHeaders resp
|
contentTypeMay resp = lookupHeader Hdr.hContentType $
|
||||||
|
NC.responseHeaders resp
|
||||||
|
|
||||||
-- Similar to mapConcurrently but limits the number of threads that
|
-- Similar to mapConcurrently but limits the number of threads that
|
||||||
-- can run using a quantity semaphore.
|
-- can run using a quantity semaphore.
|
||||||
@ -188,7 +186,7 @@ limitedMapConcurrently count act args = do
|
|||||||
mapM A.wait threads
|
mapM A.wait threads
|
||||||
where
|
where
|
||||||
wThread t arg =
|
wThread t arg =
|
||||||
UEx.bracket_ (waitSem t) (signalSem t) $ act arg
|
U.bracket_ (waitSem t) (signalSem t) $ act arg
|
||||||
|
|
||||||
-- quantity semaphore implementation using TVar
|
-- quantity semaphore implementation using TVar
|
||||||
waitSem t = U.atomically $ do
|
waitSem t = U.atomically $ do
|
||||||
|
|||||||
@ -28,14 +28,13 @@ module Network.Minio.XmlParser
|
|||||||
, parseNotification
|
, parseNotification
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Trans.Resource
|
import Data.List (zip3, zip4, zip5)
|
||||||
import Data.List (zip3, zip4, zip5)
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Map as Map
|
import Data.Text.Read (decimal)
|
||||||
import Data.Text.Read (decimal)
|
|
||||||
import Data.Time
|
import Data.Time
|
||||||
import Text.XML
|
import Text.XML
|
||||||
import Text.XML.Cursor hiding (bool)
|
import Text.XML.Cursor hiding (bool)
|
||||||
|
|
||||||
import Lib.Prelude
|
import Lib.Prelude
|
||||||
|
|
||||||
@ -55,27 +54,27 @@ uncurry5 :: (a -> b -> c -> d -> e -> f) -> (a, b, c, d, e) -> f
|
|||||||
uncurry5 f (a, b, c, d, e) = f a b c d e
|
uncurry5 f (a, b, c, d, e) = f a b c d e
|
||||||
|
|
||||||
-- | Parse time strings from XML
|
-- | Parse time strings from XML
|
||||||
parseS3XMLTime :: (MonadThrow m) => Text -> m UTCTime
|
parseS3XMLTime :: (MonadIO m) => Text -> m UTCTime
|
||||||
parseS3XMLTime = either (throwM . MErrVXmlParse) return
|
parseS3XMLTime = either (throwIO . MErrVXmlParse) return
|
||||||
. parseTimeM True defaultTimeLocale s3TimeFormat
|
. parseTimeM True defaultTimeLocale s3TimeFormat
|
||||||
. T.unpack
|
. T.unpack
|
||||||
|
|
||||||
parseDecimal :: (MonadThrow m, Integral a) => Text -> m a
|
parseDecimal :: (MonadIO m, Integral a) => Text -> m a
|
||||||
parseDecimal numStr = either (throwM . MErrVXmlParse . show) return $
|
parseDecimal numStr = either (throwIO . MErrVXmlParse . show) return $
|
||||||
fst <$> decimal numStr
|
fst <$> decimal numStr
|
||||||
|
|
||||||
parseDecimals :: (MonadThrow m, Integral a) => [Text] -> m [a]
|
parseDecimals :: (MonadIO m, Integral a) => [Text] -> m [a]
|
||||||
parseDecimals numStr = forM numStr parseDecimal
|
parseDecimals numStr = forM numStr parseDecimal
|
||||||
|
|
||||||
s3Elem :: Text -> Axis
|
s3Elem :: Text -> Axis
|
||||||
s3Elem = element . s3Name
|
s3Elem = element . s3Name
|
||||||
|
|
||||||
parseRoot :: (MonadThrow m) => LByteString -> m Cursor
|
parseRoot :: (MonadIO m) => LByteString -> m Cursor
|
||||||
parseRoot = either (throwM . MErrVXmlParse . show) (return . fromDocument)
|
parseRoot = either (throwIO . MErrVXmlParse . show) (return . fromDocument)
|
||||||
. parseLBS def
|
. parseLBS def
|
||||||
|
|
||||||
-- | Parse the response XML of a list buckets call.
|
-- | Parse the response XML of a list buckets call.
|
||||||
parseListBuckets :: (MonadThrow m) => LByteString -> m [BucketInfo]
|
parseListBuckets :: (MonadIO m) => LByteString -> m [BucketInfo]
|
||||||
parseListBuckets xmldata = do
|
parseListBuckets xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let
|
let
|
||||||
@ -86,26 +85,26 @@ parseListBuckets xmldata = do
|
|||||||
return $ zipWith BucketInfo names times
|
return $ zipWith BucketInfo names times
|
||||||
|
|
||||||
-- | Parse the response XML of a location request.
|
-- | Parse the response XML of a location request.
|
||||||
parseLocation :: (MonadThrow m) => LByteString -> m Region
|
parseLocation :: (MonadIO m) => LByteString -> m Region
|
||||||
parseLocation xmldata = do
|
parseLocation xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let region = T.concat $ r $/ content
|
let region = T.concat $ r $/ content
|
||||||
return $ bool "us-east-1" region $ region /= ""
|
return $ bool "us-east-1" region $ region /= ""
|
||||||
|
|
||||||
-- | Parse the response XML of an newMultipartUpload call.
|
-- | Parse the response XML of an newMultipartUpload call.
|
||||||
parseNewMultipartUpload :: (MonadThrow m) => LByteString -> m UploadId
|
parseNewMultipartUpload :: (MonadIO m) => LByteString -> m UploadId
|
||||||
parseNewMultipartUpload xmldata = do
|
parseNewMultipartUpload xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
return $ T.concat $ r $// s3Elem "UploadId" &/ content
|
return $ T.concat $ r $// s3Elem "UploadId" &/ content
|
||||||
|
|
||||||
-- | Parse the response XML of completeMultipartUpload call.
|
-- | Parse the response XML of completeMultipartUpload call.
|
||||||
parseCompleteMultipartUploadResponse :: (MonadThrow m) => LByteString -> m ETag
|
parseCompleteMultipartUploadResponse :: (MonadIO m) => LByteString -> m ETag
|
||||||
parseCompleteMultipartUploadResponse xmldata = do
|
parseCompleteMultipartUploadResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
return $ T.concat $ r $// s3Elem "ETag" &/ content
|
return $ T.concat $ r $// s3Elem "ETag" &/ content
|
||||||
|
|
||||||
-- | Parse the response XML of copyObject and copyObjectPart
|
-- | Parse the response XML of copyObject and copyObjectPart
|
||||||
parseCopyObjectResponse :: (MonadThrow m) => LByteString -> m (ETag, UTCTime)
|
parseCopyObjectResponse :: (MonadIO m) => LByteString -> m (ETag, UTCTime)
|
||||||
parseCopyObjectResponse xmldata = do
|
parseCopyObjectResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let
|
let
|
||||||
@ -115,7 +114,7 @@ parseCopyObjectResponse xmldata = do
|
|||||||
return (T.concat $ r $// s3Elem "ETag" &/ content, mtime)
|
return (T.concat $ r $// s3Elem "ETag" &/ content, mtime)
|
||||||
|
|
||||||
-- | Parse the response XML of a list objects v1 call.
|
-- | Parse the response XML of a list objects v1 call.
|
||||||
parseListObjectsV1Response :: (MonadThrow m)
|
parseListObjectsV1Response :: (MonadIO m)
|
||||||
=> LByteString -> m ListObjectsV1Result
|
=> LByteString -> m ListObjectsV1Result
|
||||||
parseListObjectsV1Response xmldata = do
|
parseListObjectsV1Response xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
@ -143,7 +142,7 @@ parseListObjectsV1Response xmldata = do
|
|||||||
return $ ListObjectsV1Result hasMore nextMarker objects prefixes
|
return $ ListObjectsV1Result hasMore nextMarker objects prefixes
|
||||||
|
|
||||||
-- | Parse the response XML of a list objects call.
|
-- | Parse the response XML of a list objects call.
|
||||||
parseListObjectsResponse :: (MonadThrow m) => LByteString -> m ListObjectsResult
|
parseListObjectsResponse :: (MonadIO m) => LByteString -> m ListObjectsResult
|
||||||
parseListObjectsResponse xmldata = do
|
parseListObjectsResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let
|
let
|
||||||
@ -170,7 +169,7 @@ parseListObjectsResponse xmldata = do
|
|||||||
return $ ListObjectsResult hasMore nextToken objects prefixes
|
return $ ListObjectsResult hasMore nextToken objects prefixes
|
||||||
|
|
||||||
-- | Parse the response XML of a list incomplete multipart upload call.
|
-- | Parse the response XML of a list incomplete multipart upload call.
|
||||||
parseListUploadsResponse :: (MonadThrow m) => LByteString -> m ListUploadsResult
|
parseListUploadsResponse :: (MonadIO m) => LByteString -> m ListUploadsResult
|
||||||
parseListUploadsResponse xmldata = do
|
parseListUploadsResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let
|
let
|
||||||
@ -189,7 +188,7 @@ parseListUploadsResponse xmldata = do
|
|||||||
|
|
||||||
return $ ListUploadsResult hasMore nextKey nextUpload uploads prefixes
|
return $ ListUploadsResult hasMore nextKey nextUpload uploads prefixes
|
||||||
|
|
||||||
parseListPartsResponse :: (MonadThrow m) => LByteString -> m ListPartsResult
|
parseListPartsResponse :: (MonadIO m) => LByteString -> m ListPartsResult
|
||||||
parseListPartsResponse xmldata = do
|
parseListPartsResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let
|
let
|
||||||
@ -212,14 +211,14 @@ parseListPartsResponse xmldata = do
|
|||||||
return $ ListPartsResult hasMore (listToMaybe nextPartNum) partInfos
|
return $ ListPartsResult hasMore (listToMaybe nextPartNum) partInfos
|
||||||
|
|
||||||
|
|
||||||
parseErrResponse :: (MonadThrow m) => LByteString -> m ServiceErr
|
parseErrResponse :: (MonadIO m) => LByteString -> m ServiceErr
|
||||||
parseErrResponse xmldata = do
|
parseErrResponse xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let code = T.concat $ r $/ element "Code" &/ content
|
let code = T.concat $ r $/ element "Code" &/ content
|
||||||
message = T.concat $ r $/ element "Message" &/ content
|
message = T.concat $ r $/ element "Message" &/ content
|
||||||
return $ toServiceErr code message
|
return $ toServiceErr code message
|
||||||
|
|
||||||
parseNotification :: (MonadThrow m) => LByteString -> m Notification
|
parseNotification :: (MonadIO m) => LByteString -> m Notification
|
||||||
parseNotification xmldata = do
|
parseNotification xmldata = do
|
||||||
r <- parseRoot xmldata
|
r <- parseRoot xmldata
|
||||||
let qcfg = map node $ r $/ s3Elem "QueueConfiguration"
|
let qcfg = map node $ r $/ s3Elem "QueueConfiguration"
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import Test.Tasty.HUnit
|
|||||||
import Test.Tasty.QuickCheck as QC
|
import Test.Tasty.QuickCheck as QC
|
||||||
|
|
||||||
import Conduit (replicateC)
|
import Conduit (replicateC)
|
||||||
import qualified Control.Monad.Catch as MC
|
|
||||||
import qualified Control.Monad.Trans.Resource as R
|
import qualified Control.Monad.Trans.Resource as R
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.Conduit (yield)
|
import Data.Conduit (yield)
|
||||||
@ -437,7 +436,7 @@ liveServerUnitTests = testGroup "Unit tests against a live server"
|
|||||||
liftIO $ assertEqual "storageClass did not match" (Just "REDUCED_REDUNDANCY")
|
liftIO $ assertEqual "storageClass did not match" (Just "REDUCED_REDUNDANCY")
|
||||||
(Map.lookup "X-Amz-Storage-Class" m')
|
(Map.lookup "X-Amz-Storage-Class" m')
|
||||||
|
|
||||||
fpE <- MC.try $ fPutObject bucket object'' inputFile'' def{
|
fpE <- try $ fPutObject bucket object'' inputFile'' def{
|
||||||
pooStorageClass = Just "INVALID_STORAGE_CLASS"
|
pooStorageClass = Just "INVALID_STORAGE_CLASS"
|
||||||
}
|
}
|
||||||
case fpE of
|
case fpE of
|
||||||
@ -571,13 +570,13 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
" was expected to exist.")
|
" was expected to exist.")
|
||||||
|
|
||||||
step "makeBucket again to check if BucketAlreadyOwnedByYou exception is raised."
|
step "makeBucket again to check if BucketAlreadyOwnedByYou exception is raised."
|
||||||
mbE <- MC.try $ makeBucket bucket Nothing
|
mbE <- try $ makeBucket bucket Nothing
|
||||||
case mbE of
|
case mbE of
|
||||||
Left exn -> liftIO $ exn @?= BucketAlreadyOwnedByYou
|
Left exn -> liftIO $ exn @?= BucketAlreadyOwnedByYou
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
step "makeBucket with an invalid bucket name and check for appropriate exception."
|
step "makeBucket with an invalid bucket name and check for appropriate exception."
|
||||||
invalidMBE <- MC.try $ makeBucket "invalidBucketName" Nothing
|
invalidMBE <- try $ makeBucket "invalidBucketName" Nothing
|
||||||
case invalidMBE of
|
case invalidMBE of
|
||||||
Left exn -> liftIO $ exn @?= MErrVInvalidBucketName "invalidBucketName"
|
Left exn -> liftIO $ exn @?= MErrVInvalidBucketName "invalidBucketName"
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
@ -590,7 +589,7 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
fPutObject bucket "lsb-release" "/etc/lsb-release" def
|
fPutObject bucket "lsb-release" "/etc/lsb-release" def
|
||||||
|
|
||||||
step "fPutObject onto a non-existent bucket and check for NoSuchBucket exception"
|
step "fPutObject onto a non-existent bucket and check for NoSuchBucket exception"
|
||||||
fpE <- MC.try $ fPutObject "nosuchbucket" "lsb-release" "/etc/lsb-release" def
|
fpE <- try $ fPutObject "nosuchbucket" "lsb-release" "/etc/lsb-release" def
|
||||||
case fpE of
|
case fpE of
|
||||||
Left exn -> liftIO $ exn @?= NoSuchBucket
|
Left exn -> liftIO $ exn @?= NoSuchBucket
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
@ -601,7 +600,7 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
|
|
||||||
let unmodifiedTime = UTCTime (fromGregorian 2010 11 26) 69857
|
let unmodifiedTime = UTCTime (fromGregorian 2010 11 26) 69857
|
||||||
step "fGetObject an object which is modified now but requesting as un-modified in past, check for exception"
|
step "fGetObject an object which is modified now but requesting as un-modified in past, check for exception"
|
||||||
resE <- MC.try $ fGetObject bucket "lsb-release" outFile def{
|
resE <- try $ fGetObject bucket "lsb-release" outFile def{
|
||||||
gooIfUnmodifiedSince = (Just unmodifiedTime)
|
gooIfUnmodifiedSince = (Just unmodifiedTime)
|
||||||
}
|
}
|
||||||
case resE of
|
case resE of
|
||||||
@ -609,7 +608,7 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
step "fGetObject an object with no matching etag, check for exception"
|
step "fGetObject an object with no matching etag, check for exception"
|
||||||
resE1 <- MC.try $ fGetObject bucket "lsb-release" outFile def{
|
resE1 <- try $ fGetObject bucket "lsb-release" outFile def{
|
||||||
gooIfMatch = (Just "invalid-etag")
|
gooIfMatch = (Just "invalid-etag")
|
||||||
}
|
}
|
||||||
case resE1 of
|
case resE1 of
|
||||||
@ -617,7 +616,7 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
step "fGetObject an object with no valid range, check for exception"
|
step "fGetObject an object with no valid range, check for exception"
|
||||||
resE2 <- MC.try $ fGetObject bucket "lsb-release" outFile def{
|
resE2 <- try $ fGetObject bucket "lsb-release" outFile def{
|
||||||
gooRange = (Just $ HT.ByteRangeFromTo 100 200)
|
gooRange = (Just $ HT.ByteRangeFromTo 100 200)
|
||||||
}
|
}
|
||||||
case resE2 of
|
case resE2 of
|
||||||
@ -630,7 +629,7 @@ basicTests = funTestWithBucket "Basic tests" $ \step bucket -> do
|
|||||||
}
|
}
|
||||||
|
|
||||||
step "fGetObject a non-existent object and check for NoSuchKey exception"
|
step "fGetObject a non-existent object and check for NoSuchKey exception"
|
||||||
resE3 <- MC.try $ fGetObject bucket "noSuchKey" outFile def
|
resE3 <- try $ fGetObject bucket "noSuchKey" outFile def
|
||||||
case resE3 of
|
case resE3 of
|
||||||
Left exn -> liftIO $ exn @?= NoSuchKey
|
Left exn -> liftIO $ exn @?= NoSuchKey
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
@ -705,7 +704,7 @@ presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
|
|||||||
step "HEAD object presigned URL - presignedHeadObjectUrl"
|
step "HEAD object presigned URL - presignedHeadObjectUrl"
|
||||||
headUrl <- presignedHeadObjectUrl bucket obj2 3600 []
|
headUrl <- presignedHeadObjectUrl bucket obj2 3600 []
|
||||||
|
|
||||||
headResp <- do req <- NC.parseRequest $ toS headUrl
|
headResp <- do let req = NC.parseRequest_ $ toS headUrl
|
||||||
NC.httpLbs (req {NC.method = HT.methodHead}) mgr
|
NC.httpLbs (req {NC.method = HT.methodHead}) mgr
|
||||||
liftIO $ (NC.responseStatus headResp == HT.status200) @?
|
liftIO $ (NC.responseStatus headResp == HT.status200) @?
|
||||||
"presigned HEAD failed (presignedHeadObjectUrl)"
|
"presigned HEAD failed (presignedHeadObjectUrl)"
|
||||||
@ -731,14 +730,14 @@ presignedUrlFunTest = funTestWithBucket "presigned Url tests" $
|
|||||||
mapM_ (removeObject bucket) [obj, obj2]
|
mapM_ (removeObject bucket) [obj, obj2]
|
||||||
where
|
where
|
||||||
putR size filePath mgr url = do
|
putR size filePath mgr url = do
|
||||||
req <- NC.parseRequest $ toS url
|
let req = NC.parseRequest_ $ toS url
|
||||||
let req' = req { NC.method = HT.methodPut
|
let req' = req { NC.method = HT.methodPut
|
||||||
, NC.requestBody = NC.requestBodySource size $
|
, NC.requestBody = NC.requestBodySource size $
|
||||||
CB.sourceFile filePath}
|
CB.sourceFile filePath}
|
||||||
NC.httpLbs req' mgr
|
NC.httpLbs req' mgr
|
||||||
|
|
||||||
getR mgr url = do
|
getR mgr url = do
|
||||||
req <- NC.parseRequest $ toS url
|
let req = NC.parseRequest_ $ toS url
|
||||||
NC.httpLbs req mgr
|
NC.httpLbs req mgr
|
||||||
|
|
||||||
presignedPostPolicyFunTest :: TestTree
|
presignedPostPolicyFunTest :: TestTree
|
||||||
@ -789,12 +788,12 @@ bucketPolicyFunTest = funTestWithBucket "Bucket Policy tests" $
|
|||||||
\step bucket -> do
|
\step bucket -> do
|
||||||
|
|
||||||
step "bucketPolicy basic test - no policy exception"
|
step "bucketPolicy basic test - no policy exception"
|
||||||
resE <- MC.try $ getBucketPolicy bucket
|
resE <- try $ getBucketPolicy bucket
|
||||||
case resE of
|
case resE of
|
||||||
Left exn -> liftIO $ exn @?= ServiceErr "NoSuchBucketPolicy" "The bucket policy does not exist"
|
Left exn -> liftIO $ exn @?= ServiceErr "NoSuchBucketPolicy" "The bucket policy does not exist"
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
resE' <- MC.try $ setBucketPolicy bucket T.empty
|
resE' <- try $ setBucketPolicy bucket T.empty
|
||||||
case resE' of
|
case resE' of
|
||||||
Left exn -> liftIO $ exn @?= ServiceErr "NoSuchBucketPolicy" "The bucket policy does not exist"
|
Left exn -> liftIO $ exn @?= ServiceErr "NoSuchBucketPolicy" "The bucket policy does not exist"
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
@ -802,7 +801,7 @@ bucketPolicyFunTest = funTestWithBucket "Bucket Policy tests" $
|
|||||||
let expectedPolicyJSON = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::testbucket\"]},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::testbucket/*\"]}]}"
|
let expectedPolicyJSON = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::testbucket\"]},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::testbucket/*\"]}]}"
|
||||||
|
|
||||||
step "try a malformed policy, expect error"
|
step "try a malformed policy, expect error"
|
||||||
resE'' <- MC.try $ setBucketPolicy bucket expectedPolicyJSON
|
resE'' <- try $ setBucketPolicy bucket expectedPolicyJSON
|
||||||
case resE'' of
|
case resE'' of
|
||||||
Left exn -> liftIO $ exn @?= ServiceErr "MalformedPolicy" "Policy has invalid resource."
|
Left exn -> liftIO $ exn @?= ServiceErr "MalformedPolicy" "Policy has invalid resource."
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|||||||
@ -19,16 +19,15 @@ module Network.Minio.XmlParser.Test
|
|||||||
xmlParserTests
|
xmlParserTests
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Control.Monad.Catch as MC
|
import Data.Default (def)
|
||||||
import Data.Time (fromGregorian)
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import Data.Time (fromGregorian)
|
||||||
import Test.Tasty
|
import Test.Tasty
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
|
import UnliftIO (MonadUnliftIO)
|
||||||
|
|
||||||
import Lib.Prelude
|
import Lib.Prelude
|
||||||
|
|
||||||
import Data.Default (def)
|
|
||||||
|
|
||||||
import Network.Minio.Data
|
import Network.Minio.Data
|
||||||
import Network.Minio.Errors
|
import Network.Minio.Errors
|
||||||
import Network.Minio.XmlParser
|
import Network.Minio.XmlParser
|
||||||
@ -46,8 +45,8 @@ xmlParserTests = testGroup "XML Parser Tests"
|
|||||||
, testCase "Test parseNotification" testParseNotification
|
, testCase "Test parseNotification" testParseNotification
|
||||||
]
|
]
|
||||||
|
|
||||||
tryValidationErr :: (MC.MonadCatch m) => m a -> m (Either MErrV a)
|
tryValidationErr :: (MonadUnliftIO m) => m a -> m (Either MErrV a)
|
||||||
tryValidationErr act = MC.try act
|
tryValidationErr act = try act
|
||||||
|
|
||||||
assertValidtionErr :: MErrV -> Assertion
|
assertValidtionErr :: MErrV -> Assertion
|
||||||
assertValidtionErr e = assertFailure $ "Failed due to validation error => " ++ show e
|
assertValidtionErr e = assertFailure $ "Failed due to validation error => " ++ show e
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user