Update formatting with latest ormolu 1.4 (#163)

This commit is contained in:
Aditya Manthramurthy 2021-03-03 16:11:45 -08:00 committed by GitHub
parent 73bc5b64a0
commit b8cc1e57ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 249 additions and 214 deletions

View File

@ -34,9 +34,9 @@ main = do
-- Performs a recursive listing of incomplete uploads under bucket "test"
-- on a local minio server.
res <-
runMinio minioPlayCI
$ runConduit
$ listIncompleteUploads bucket Nothing True .| mapM_C (\v -> (liftIO $ print v))
runMinio minioPlayCI $
runConduit $
listIncompleteUploads bucket Nothing True .| mapM_C (\v -> (liftIO $ print v))
print res
{-

View File

@ -34,9 +34,9 @@ main = do
-- Performs a recursive listing of all objects under bucket "test"
-- on play.min.io.
res <-
runMinio minioPlayCI
$ runConduit
$ listObjects bucket Nothing True .| mapM_C (\v -> (liftIO $ print v))
runMinio minioPlayCI $
runConduit $
listObjects bucket Nothing True .| mapM_C (\v -> (liftIO $ print v))
print res
{-

View File

@ -73,7 +73,8 @@ main = do
]
formOptions = B.intercalate " " $ map formFn $ H.toList formData
return $ B.intercalate " " $
return $
B.intercalate " " $
["curl", formOptions, "-F file=@/tmp/photo.jpg", url]
case res of

View File

@ -55,6 +55,7 @@ module Network.Minio
gcsCI,
-- * Minio Monad
----------------
-- | The Minio Monad provides connection-reuse, bucket-location

View File

@ -186,9 +186,9 @@ buildRequest ri = do
retryAPIRequest :: Minio a -> Minio a
retryAPIRequest apiCall = do
resE <-
retrying retryPolicy (const shouldRetry)
$ const
$ try apiCall
retrying retryPolicy (const shouldRetry) $
const $
try apiCall
either throwIO return resE
where
-- Retry using the full-jitter backoff method for up to 10 mins
@ -266,9 +266,9 @@ isValidBucketName bucket =
-- Throws exception iff bucket name is invalid according to AWS rules.
checkBucketNameValidity :: MonadIO m => Bucket -> m ()
checkBucketNameValidity bucket =
when (not $ isValidBucketName bucket)
$ throwIO
$ MErrVInvalidBucketName bucket
when (not $ isValidBucketName bucket) $
throwIO $
MErrVInvalidBucketName bucket
isValidObjectName :: Object -> Bool
isValidObjectName object =
@ -276,6 +276,6 @@ isValidObjectName object =
checkObjectNameValidity :: MonadIO m => Object -> m ()
checkObjectNameValidity object =
when (not $ isValidObjectName object)
$ throwIO
$ MErrVInvalidObjectName object
when (not $ isValidObjectName object) $
throwIO $
MErrVInvalidObjectName object

View File

@ -16,6 +16,7 @@
module Network.Minio.AdminAPI
( -- * MinIO Admin API
--------------------
-- | Provides MinIO admin API and related types. It is in
@ -52,10 +53,7 @@ module Network.Minio.AdminAPI
where
import Data.Aeson
( (.:),
(.:?),
(.=),
FromJSON,
( FromJSON,
ToJSON,
Value (Object),
eitherDecode,
@ -66,6 +64,9 @@ import Data.Aeson
toJSON,
withObject,
withText,
(.:),
(.:?),
(.=),
)
import qualified Data.Aeson as A
import Data.Aeson.Types (typeMismatch)
@ -610,9 +611,9 @@ buildAdminRequest areq = do
areq
{ ariPayloadHash = Just sha256Hash,
ariHeaders =
hostHeader
: sha256Header sha256Hash
: ariHeaders areq
hostHeader :
sha256Header sha256Hash :
ariHeaders areq
}
signReq = toRequest ci newAreq
sp =

View File

@ -51,8 +51,8 @@ copyObjectInternal b' o srcInfo = do
endOffset >= fromIntegral srcSize
]
)
$ throwIO
$ MErrVInvalidSrcObjByteRange range
$ throwIO $
MErrVInvalidSrcObjByteRange range
-- 1. If sz > 64MiB (minPartSize) use multipart copy, OR
-- 2. If startOffset /= 0 use multipart copy
@ -69,9 +69,9 @@ copyObjectInternal b' o srcInfo = do
-- used is minPartSize.
selectCopyRanges :: (Int64, Int64) -> [(PartNumber, (Int64, Int64))]
selectCopyRanges (st, end) =
zip pns
$ map (\(x, y) -> (st + x, st + x + y - 1))
$ zip startOffsets partSizes
zip pns $
map (\(x, y) -> (st + x, st + x + y - 1)) $
zip startOffsets partSizes
where
size = end - st + 1
(pns, startOffsets, partSizes) = List.unzip3 $ selectPartSizes size

View File

@ -38,7 +38,9 @@ class UriEncodable s where
instance UriEncodable [Char] where
uriEncode encodeSlash payload =
LB.toStrict $ BB.toLazyByteString $ mconcat $
LB.toStrict $
BB.toLazyByteString $
mconcat $
map (`uriEncodeChar` encodeSlash) payload
instance UriEncodable ByteString where

View File

@ -20,11 +20,11 @@ module Network.Minio.JsonParser
where
import Data.Aeson
( (.:),
FromJSON,
( FromJSON,
eitherDecode,
parseJSON,
withObject,
(.:),
)
import qualified Data.Text as T
import Lib.Prelude

View File

@ -51,10 +51,10 @@ listObjects bucket prefix recurse = loop Nothing
res <- lift $ listObjects' bucket prefix nextToken delimiter Nothing
CL.sourceList $ map ListItemObject $ lorObjects res
unless recurse
$ CL.sourceList
$ map ListItemPrefix
$ lorCPrefixes res
unless recurse $
CL.sourceList $
map ListItemPrefix $
lorCPrefixes res
when (lorHasMore res) $
loop (lorNextToken res)
@ -73,10 +73,10 @@ listObjectsV1 bucket prefix recurse = loop Nothing
res <- lift $ listObjectsV1' bucket prefix nextMarker delimiter Nothing
CL.sourceList $ map ListItemObject $ lorObjects' res
unless recurse
$ CL.sourceList
$ map ListItemPrefix
$ lorCPrefixes' res
unless recurse $
CL.sourceList $
map ListItemPrefix $
lorCPrefixes' res
when (lorHasMore' res) $
loop (lorNextMarker res)
@ -104,15 +104,16 @@ listIncompleteUploads bucket prefix recurse = loop Nothing Nothing
nextUploadIdMarker
Nothing
aggrSizes <- lift $ forM (lurUploads res) $ \(uKey, uId, _) -> do
aggrSizes <- lift $
forM (lurUploads res) $ \(uKey, uId, _) -> do
partInfos <-
C.runConduit $
listIncompleteParts bucket uKey uId
C..| CC.sinkList
return $ foldl (\sizeSofar p -> opiSize p + sizeSofar) 0 partInfos
CL.sourceList
$ map
CL.sourceList $
map
( \((uKey, uId, uInitTime), size) ->
UploadInfo uKey uId uInitTime size
)

View File

@ -68,9 +68,9 @@ makePresignedUrl ::
HT.RequestHeaders ->
Minio ByteString
makePresignedUrl expiry method bucket object region extraQuery extraHeaders = do
when (expiry > 7 * 24 * 3600 || expiry < 0)
$ throwIO
$ MErrVInvalidUrlExpiry expiry
when (expiry > 7 * 24 * 3600 || expiry < 0) $
throwIO $
MErrVInvalidUrlExpiry expiry
ci <- asks mcConnInfo
@ -103,7 +103,9 @@ makePresignedUrl expiry method bucket object region extraQuery extraHeaders = do
((HT.parseQuery $ NC.queryString req) ++ qpToAdd)
scheme = byteString $ bool "http://" "https://" $ connectIsSecure ci
return $ toStrictBS $ toLazyByteString $
return $
toStrictBS $
toLazyByteString $
scheme
<> byteString (getHostAddr ci)
<> byteString (getS3Path bucket object)
@ -331,7 +333,9 @@ presignedPostPolicy p = do
mkPair (PPCEquals k v) = Just (k, v)
mkPair _ = Nothing
formFromPolicy =
H.map toUtf8 $ H.fromList $ catMaybes $
H.map toUtf8 $
H.fromList $
catMaybes $
mkPair <$> conditions ppWithCreds
formData = formFromPolicy `H.union` signData
-- compute POST upload URL
@ -339,7 +343,8 @@ presignedPostPolicy p = do
scheme = byteString $ bool "http://" "https://" $ connectIsSecure ci
region = connectRegion ci
url =
toStrictBS $ toLazyByteString $
toStrictBS $
toLazyByteString $
scheme <> byteString (getHostAddr ci)
<> byteString "/"
<> byteString bucket

View File

@ -19,10 +19,12 @@ module Network.Minio.S3API
getLocation,
-- * Listing buckets
--------------------
getService,
-- * Listing objects
--------------------
ListObjectsResult (..),
ListObjectsV1Result (..),
@ -33,11 +35,13 @@ module Network.Minio.S3API
headBucket,
-- * Retrieving objects
-----------------------
getObject',
headObject,
-- * Creating buckets and objects
---------------------------------
putBucket,
ETag,
@ -47,6 +51,7 @@ module Network.Minio.S3API
copyObjectSingle,
-- * Multipart Upload APIs
--------------------------
UploadId,
PartTuple,
@ -63,11 +68,13 @@ module Network.Minio.S3API
listIncompleteParts',
-- * Deletion APIs
--------------------------
deleteBucket,
deleteObject,
-- * Presigned Operations
-----------------------------
module Network.Minio.PresignedOperations,
@ -76,6 +83,7 @@ module Network.Minio.S3API
setBucketPolicy,
-- * Bucket Notifications
-------------------------
Notification (..),
NotificationConfig (..),
@ -157,7 +165,8 @@ getObject' bucket object queryParams headers = do
{ riBucket = Just bucket,
riObject = Just object,
riQueryParams = queryParams,
riHeaders = headers
riHeaders =
headers
-- This header is required for safety as otherwise http-client,
-- sends Accept-Encoding: gzip, and the server may actually gzip
-- body. In that case Content-Length header will be missing.
@ -168,7 +177,8 @@ getObject' bucket object queryParams headers = do
putBucket :: Bucket -> Region -> Minio ()
putBucket bucket location = do
ns <- asks getSvcNamespace
void $ executeRequest $
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodPut,
riBucket = Just bucket,
@ -188,9 +198,9 @@ putObjectSingle' :: Bucket -> Object -> [HT.Header] -> ByteString -> Minio ETag
putObjectSingle' bucket object headers bs = do
let size = fromIntegral (BS.length bs)
-- check length is within single PUT object size.
when (size > maxSinglePutObjectSizeBytes)
$ throwIO
$ MErrVSinglePUTSizeExceeded size
when (size > maxSinglePutObjectSizeBytes) $
throwIO $
MErrVSinglePUTSizeExceeded size
let payload = mkStreamingPayload $ PayloadBS bs
resp <-
@ -222,9 +232,9 @@ putObjectSingle ::
Minio ETag
putObjectSingle bucket object headers h offset size = do
-- check length is within single PUT object size.
when (size > maxSinglePutObjectSizeBytes)
$ throwIO
$ MErrVSinglePUTSizeExceeded size
when (size > maxSinglePutObjectSizeBytes) $
throwIO $
MErrVSinglePUTSizeExceeded size
-- content-length header is automatically set by library.
let payload = mkStreamingPayload $ PayloadH h offset size
@ -301,9 +311,9 @@ listObjects' bucket prefix nextToken delimiter maxKeys = do
-- | DELETE a bucket from the service.
deleteBucket :: Bucket -> Minio ()
deleteBucket bucket =
void
$ executeRequest
$ defaultS3ReqInfo
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodDelete,
riBucket = Just bucket
}
@ -311,9 +321,9 @@ deleteBucket bucket =
-- | DELETE an object from the service.
deleteObject :: Bucket -> Object -> Minio ()
deleteObject bucket object =
void
$ executeRequest
$ defaultS3ReqInfo
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodDelete,
riBucket = Just bucket,
riObject = Just object
@ -377,8 +387,8 @@ srcInfoToHeaders srcInfo =
"/",
srcObject srcInfo
]
)
: rangeHdr
) :
rangeHdr
++ zip names values
where
names =
@ -477,9 +487,9 @@ completeMultipartUpload bucket object uploadId partTuple = do
-- | Abort a multipart upload.
abortMultipartUpload :: Bucket -> Object -> UploadId -> Minio ()
abortMultipartUpload bucket object uploadId =
void
$ executeRequest
$ defaultS3ReqInfo
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodDelete,
riBucket = Just bucket,
riObject = Just object,
@ -509,8 +519,8 @@ listIncompleteUploads' bucket prefix delimiter keyMarker uploadIdMarker maxKeys
where
-- build query params
params =
("uploads", Nothing)
: mkOptionalParams
("uploads", Nothing) :
mkOptionalParams
[ ("prefix", prefix),
("delimiter", delimiter),
("key-marker", keyMarker),
@ -553,15 +563,16 @@ headObject bucket object reqHeaders = do
{ riMethod = HT.methodHead,
riBucket = Just bucket,
riObject = Just object,
riHeaders = reqHeaders
riHeaders =
reqHeaders
-- This header is required for safety as otherwise http-client,
-- sends Accept-Encoding: gzip, and the server may actually gzip
-- body. In that case Content-Length header will be missing.
<> [("Accept-Encoding", "identity")]
}
maybe (throwIO MErrVInvalidObjectInfoResponse) return
$ parseGetObjectHeaders object
$ NC.responseHeaders resp
maybe (throwIO MErrVInvalidObjectInfoResponse) return $
parseGetObjectHeaders object $
NC.responseHeaders resp
-- | Query the object store if a given bucket exists.
headBucket :: Bucket -> Minio Bool
@ -594,7 +605,8 @@ headBucket bucket =
putBucketNotification :: Bucket -> Notification -> Minio ()
putBucketNotification bucket ncfg = do
ns <- asks getSvcNamespace
void $ executeRequest $
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodPut,
riBucket = Just bucket,
@ -644,7 +656,8 @@ setBucketPolicy bucket policy = do
-- | Save a new policy on a bucket.
putBucketPolicy :: Bucket -> Text -> Minio ()
putBucketPolicy bucket policy = do
void $ executeRequest $
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodPut,
riBucket = Just bucket,
@ -655,7 +668,8 @@ putBucketPolicy bucket policy = do
-- | Delete any policy set on a bucket.
deleteBucketPolicy :: Bucket -> Minio ()
deleteBucketPolicy bucket = do
void $ executeRequest $
void $
executeRequest $
defaultS3ReqInfo
{ riMethod = HT.methodDelete,
riBucket = Just bucket,

View File

@ -198,10 +198,10 @@ mkCanonicalRequest ::
ByteString
mkCanonicalRequest !isStreaming !sp !req !headersForSign =
let canonicalQueryString =
B.intercalate "&"
$ map (\(x, y) -> B.concat [x, "=", y])
$ sort
$ map
B.intercalate "&" $
map (\(x, y) -> B.concat [x, "=", y]) $
sort $
map
( \(x, y) ->
(uriEncode True x, maybe "" (uriEncode True) y)
)
@ -298,8 +298,8 @@ signV4Stream !payloadLength !sp !req =
in case ceMay of
Nothing -> ("content-encoding", "aws-chunked") : hs
Just (_, ce) ->
("content-encoding", ce <> ",aws-chunked")
: filter (\(x, _) -> x /= "content-encoding") hs
("content-encoding", ce <> ",aws-chunked") :
filter (\(x, _) -> x /= "content-encoding") hs
-- headers to be added to the request
datePair = ("X-Amz-Date", awsTimeFormatBS ts)
computedHeaders =

View File

@ -170,7 +170,8 @@ httpLbs req mgr = do
sErr <- parseErrResponseJSON $ NC.responseBody resp
throwIO sErr
_ ->
throwIO $ NC.HttpExceptionRequest req $
throwIO $
NC.HttpExceptionRequest req $
NC.StatusCodeException (void resp) (showBS resp)
return resp
@ -199,7 +200,8 @@ http req mgr = do
throwIO sErr
_ -> do
content <- LB.toStrict . NC.responseBody <$> NC.lbsResponse resp
throwIO $ NC.HttpExceptionRequest req $
throwIO $
NC.HttpExceptionRequest req $
NC.StatusCodeException (void resp) content
return resp
@ -265,9 +267,9 @@ chunkBSConduit (s : ss) = do
-- be 64MiB.
selectPartSizes :: Int64 -> [(PartNumber, Int64, Int64)]
selectPartSizes size =
uncurry (List.zip3 [1 ..])
$ List.unzip
$ loop 0 size
uncurry (List.zip3 [1 ..]) $
List.unzip $
loop 0 size
where
ceil :: Double -> Int64
ceil = ceiling

View File

@ -56,9 +56,9 @@ uncurry6 f (a, b, c, d, e, g) = f a b c d e g
-- | Parse time strings from XML
parseS3XMLTime :: MonadIO m => Text -> m UTCTime
parseS3XMLTime t =
maybe (throwIO $ MErrVXmlParse $ "timestamp parse failure: " <> t) return
$ parseTimeM True defaultTimeLocale s3TimeFormat
$ T.unpack t
maybe (throwIO $ MErrVXmlParse $ "timestamp parse failure: " <> t) return $
parseTimeM True defaultTimeLocale s3TimeFormat $
T.unpack t
parseDecimal :: (MonadIO m, Integral a) => Text -> m a
parseDecimal numStr =

View File

@ -134,9 +134,9 @@ basicTests = funTestWithBucket "Basic tests" $
\step bucket -> do
step "getService works and contains the test bucket."
buckets <- getService
unless (length (filter (== bucket) $ map biName buckets) == 1)
$ liftIO
$ assertFailure
unless (length (filter (== bucket) $ map biName buckets) == 1) $
liftIO $
assertFailure
( "The bucket " ++ show bucket
++ " was expected to exist."
)
@ -361,21 +361,23 @@ highLevelListingTest = funTestWithBucket "High-level listObjects Test" $
step "High-level listing of objects"
items <- C.runConduit $ listObjects bucket Nothing False C..| sinkList
liftIO $ assertEqual "Objects/Dirs match failed!" expectedNonRecList $
liftIO $
assertEqual "Objects/Dirs match failed!" expectedNonRecList $
extractObjectsAndDirsFromList items
step "High-level recursive listing of objects"
objects <- C.runConduit $ listObjects bucket Nothing True C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects match failed!"
(Just $ sort expectedObjects)
$ extractObjectsFromList objects
step "High-level listing of objects (version 1)"
itemsV1 <- C.runConduit $ listObjectsV1 bucket Nothing False C..| sinkList
liftIO $ assertEqual "Objects/Dirs match failed!" expectedNonRecList $
liftIO $
assertEqual "Objects/Dirs match failed!" expectedNonRecList $
extractObjectsAndDirsFromList itemsV1
step "High-level recursive listing of objects (version 1)"
@ -384,8 +386,8 @@ highLevelListingTest = funTestWithBucket "High-level listObjects Test" $
listObjectsV1 bucket Nothing True
C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects match failed!"
(Just $ sort expectedObjects)
$ extractObjectsFromList objectsV1
@ -394,32 +396,32 @@ highLevelListingTest = funTestWithBucket "High-level listObjects Test" $
expectedPrefListingRec = Just ["dir/dir1/o2", "dir/dir2/o3", "dir/o1"]
step "High-level listing with prefix"
prefItems <- C.runConduit $ listObjects bucket (Just "dir/") False C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects/Dirs under prefix match failed!"
expectedPrefListing
$ extractObjectsAndDirsFromList prefItems
step "High-level listing with prefix recursive"
prefItemsRec <- C.runConduit $ listObjects bucket (Just "dir/") True C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects/Dirs under prefix match recursive failed!"
expectedPrefListingRec
$ extractObjectsFromList prefItemsRec
step "High-level listing with prefix (version 1)"
prefItemsV1 <- C.runConduit $ listObjectsV1 bucket (Just "dir/") False C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects/Dirs under prefix match failed!"
expectedPrefListing
$ extractObjectsAndDirsFromList prefItemsV1
step "High-level listing with prefix recursive (version 1)"
prefItemsRecV1 <- C.runConduit $ listObjectsV1 bucket (Just "dir/") True C..| sinkList
liftIO
$ assertEqual
liftIO $
assertEqual
"Objects/Dirs under prefix match recursive failed!"
expectedPrefListingRec
$ extractObjectsFromList prefItemsRecV1
@ -910,7 +912,8 @@ putObjectUserMetadataTest = funTestWithBucket "putObject user-metadata test" $
let m = oiUserMetadata oi
-- need to do a case-insensitive comparison
sortedMeta =
sort $ map (\(k, v) -> (T.toLower k, T.toLower v)) $
sort $
map (\(k, v) -> (T.toLower k, T.toLower v)) $
H.toList m
ref = sort [("mykey1", "myval1"), ("mykey2", "myval2")]
@ -944,7 +947,8 @@ getObjectTest = funTestWithBucket "getObject test" $
let m = oiUserMetadata $ gorObjectInfo gor
-- need to do a case-insensitive comparison
sortedMeta =
sort $ map (\(k, v) -> (T.toLower k, T.toLower v)) $
sort $
map (\(k, v) -> (T.toLower k, T.toLower v)) $
H.toList m
ref = sort [("mykey1", "myval1"), ("mykey2", "myval2")]

View File

@ -63,7 +63,8 @@ parseServerInfoJSONTest =
testGroup "Parse MinIO Admin API ServerInfo JSON test" $
map
( \(tName, tDesc, tfn, tVal) ->
testCase tName $ assertBool tDesc $
testCase tName $
assertBool tDesc $
tfn (eitherDecode tVal :: Either [Char] [ServerInfo])
)
testCases
@ -82,7 +83,8 @@ parseHealStatusTest =
testGroup "Parse MinIO Admin API HealStatus JSON test" $
map
( \(tName, tDesc, tfn, tVal) ->
testCase tName $ assertBool tDesc $
testCase tName $
assertBool tDesc $
tfn (eitherDecode tVal :: Either [Char] HealStatus)
)
testCases
@ -101,7 +103,8 @@ parseHealStartRespTest =
testGroup "Parse MinIO Admin API HealStartResp JSON test" $
map
( \(tName, tDesc, tfn, tVal) ->
testCase tName $ assertBool tDesc $
testCase tName $
assertBool tDesc $
tfn (eitherDecode tVal :: Either [Char] HealStartResp)
)
testCases

View File

@ -43,9 +43,9 @@ testParseErrResponseJSON :: Assertion
testParseErrResponseJSON = do
-- 1. Test parsing of an invalid error json.
parseResE <- tryValidationErr $ parseErrResponseJSON "ClearlyInvalidJSON"
when (isRight parseResE)
$ assertFailure
$ "Parsing should have failed => " ++ show parseResE
when (isRight parseResE) $
assertFailure $
"Parsing should have failed => " ++ show parseResE
forM_ cases $ \(jsondata, sErr) -> do
parseErr <- tryValidationErr $ parseErrResponseJSON jsondata

View File

@ -62,9 +62,9 @@ testParseLocation :: Assertion
testParseLocation = do
-- 1. Test parsing of an invalid location constraint xml.
parseResE <- tryValidationErr $ parseLocation "ClearlyInvalidXml"
when (isRight parseResE)
$ assertFailure
$ "Parsing should have failed => " ++ show parseResE
when (isRight parseResE) $
assertFailure $
"Parsing should have failed => " ++ show parseResE
forM_ cases $ \(xmldata, expectedLocation) -> do
parseLocE <- tryValidationErr $ parseLocation xmldata
@ -344,7 +344,8 @@ testParseNotification = do
"1"
"arn:aws:sqs:us-west-2:444455556666:s3notificationqueue"
[ObjectCreatedPut]
( Filter $ FilterKey $
( Filter $
FilterKey $
FilterRules
[ FilterRule "prefix" "images/",
FilterRule "suffix" ".jpg"