Copyright | © Herbert Valerio Riedel 2016-2019 |
---|---|
License | GPL-3.0-or-later |
Safe Haskell | None |
Language | Haskell2010 |
Simple lightweight S3 API implementation
This implementation has been tested succesfully against MinIO's, Dreamhost's, and AWS' S3 server implementations
API Usage Example
The example below shows how to create, populate, list, and finally destroy a bucket again.
-- demo credentials for http://play.min.io/ let s3cfg =defaultS3Cfg
{s3cfgBaseUrl
= "https://play.min.io:9000" } creds =Credentials
"Q3AM3UQ867SPQQA43P2F" "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" -- we'll create this bucket and delete it again let testBucket =BucketId
"haskell-test-bucket-42"withConnection
s3cfg $ conn -> docreateBucket
conn creds testBucket Nothing etag1 <-putObject
conn creds testBucket (ObjKey
"folder/file1") "content1" (CType "text/plain") Nothing etag2 <-putObject
conn creds testBucket (ObjKey
"file2") "content2" (CType "text/plain") Nothing -- will list the key "file2" and the common-prefix "folder/" print =<<listObjects
conn creds testBucketnullObjKey
(Just '/') -- will list only the key "folder/file1" print =<<listObjects
conn creds testBucket (ObjKey
"folder/") (Just '/') -- will list the two keys "folder/file1" and "file2" (and no common prefix) print =<<listObjects
conn creds testBucketnullObjKey
Nothing -- ...and now we remove the two objects we created abovedeleteObject
conn creds testBucket (ObjKey
"folder/file1")deleteObject
conn creds testBucket (ObjKey
"file2")deleteBucket
conn creds testBucket
Synopsis
- newtype BucketId = BucketId ShortByteString
- data BucketInfo = BucketInfo !BucketId !UTCTime
- data Acl
- listBuckets :: Connection -> Credentials -> IO [BucketInfo]
- createBucket :: Connection -> Credentials -> BucketId -> Maybe Acl -> IO ()
- deleteBucket :: Connection -> Credentials -> BucketId -> IO ()
- listObjects :: Connection -> Credentials -> BucketId -> ObjKey -> Maybe Char -> IO ([ObjMetaInfo], [ObjKey])
- listObjectsFold :: Connection -> Credentials -> BucketId -> ObjKey -> Maybe Char -> Word16 -> a -> (a -> [ObjMetaInfo] -> [ObjKey] -> IO a) -> IO a
- listObjectsChunk :: Connection -> Credentials -> BucketId -> ObjKey -> Maybe Char -> ObjKey -> Word16 -> IO (ObjKey, [ObjMetaInfo], [ObjKey])
- newtype ObjKey = ObjKey ShortText
- isNullObjKey :: ObjKey -> Bool
- nullObjKey :: ObjKey
- data ObjMetaInfo = OMI {}
- newtype CType = CType ShortText
- noCType :: CType
- data ETag
- = ETag !ShortByteString
- | ETagMD5 !MD5Val
- data MD5Val
- md5hash :: ByteString -> MD5Val
- md5hex :: MD5Val -> ByteString
- md5unhex :: ByteString -> Maybe MD5Val
- md5ToSBS :: MD5Val -> ShortByteString
- md5FromSBS :: ShortByteString -> Maybe MD5Val
- putObject :: Connection -> Credentials -> BucketId -> ObjKey -> ByteString -> CType -> Maybe Acl -> IO ETag
- copyObject :: Connection -> Credentials -> BucketId -> ObjKey -> (BucketId, ObjKey) -> Maybe Acl -> IO ETag
- getObject :: Connection -> Credentials -> BucketId -> ObjKey -> IO (ETag, CType, ByteString)
- deleteObject :: Connection -> Credentials -> BucketId -> ObjKey -> IO ()
- data Condition
- = IfExists
- | IfNotExists
- | IfMatch !ETag
- | IfNotMatch !ETag
- putObjectCond :: Connection -> Credentials -> BucketId -> ObjKey -> ByteString -> CType -> Maybe Acl -> Condition -> IO (Maybe ETag)
- getObjectCond :: Connection -> Credentials -> BucketId -> ObjKey -> Condition -> IO (Maybe (ETag, CType, ByteString))
- deleteObjectCond :: Connection -> Credentials -> BucketId -> ObjKey -> Condition -> IO Bool
- data ErrorCode
- data ProtocolError
- data Credentials = Credentials {}
- noCredentials :: Credentials
- data S3Cfg = S3Cfg {}
- defaultS3Cfg :: S3Cfg
- data SignatureVersion
- data Connection
- withConnection :: S3Cfg -> (Connection -> IO a) -> IO a
- connect :: S3Cfg -> IO Connection
- close :: Connection -> IO ()
Operations on Buckets
S3 Bucket identifier
BucketId ShortByteString | Must be valid as DNS name component; S3 server implementations may have additional restrictions (see e.g. AWS S3's "Rules for Bucket Naming") |
Instances
Eq BucketId Source # | |
Ord BucketId Source # | |
Defined in Network.S3.Types | |
Show BucketId Source # | |
Generic BucketId Source # | |
NFData BucketId Source # | |
Defined in Network.S3.Types | |
Hashable BucketId Source # | |
Defined in Network.S3.Types | |
type Rep BucketId Source # | |
Defined in Network.S3.Types type Rep BucketId = D1 (MetaData "BucketId" "Network.S3.Types" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" True) (C1 (MetaCons "BucketId" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 ShortByteString))) |
data BucketInfo Source #
Bucket metadata reported by listBuckets
Instances
Show BucketInfo Source # | |
Defined in Network.S3 showsPrec :: Int -> BucketInfo -> ShowS # show :: BucketInfo -> String # showList :: [BucketInfo] -> ShowS # | |
Generic BucketInfo Source # | |
Defined in Network.S3 type Rep BucketInfo :: Type -> Type # from :: BucketInfo -> Rep BucketInfo x # to :: Rep BucketInfo x -> BucketInfo # | |
NFData BucketInfo Source # | |
Defined in Network.S3 rnf :: BucketInfo -> () # | |
type Rep BucketInfo Source # | |
Defined in Network.S3 type Rep BucketInfo = D1 (MetaData "BucketInfo" "Network.S3" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) (C1 (MetaCons "BucketInfo" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 BucketId) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 UTCTime))) |
Access permissions (aka Canned ACLs)
This has different meanings depending on whether it's set for buckets or objects
The owner of an entity has always full read & write access
For buckets, read access denotes the ability to list objects
Instances
Show Acl Source # | |
Generic Acl Source # | |
NFData Acl Source # | |
Defined in Network.S3 | |
type Rep Acl Source # | |
Defined in Network.S3 type Rep Acl = D1 (MetaData "Acl" "Network.S3" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) ((C1 (MetaCons "AclPrivate" PrefixI False) (U1 :: Type -> Type) :+: C1 (MetaCons "AclPublicRead" PrefixI False) (U1 :: Type -> Type)) :+: (C1 (MetaCons "AclPublicReadWrite" PrefixI False) (U1 :: Type -> Type) :+: C1 (MetaCons "AclPublicAuthenticatedRead" PrefixI False) (U1 :: Type -> Type))) |
listBuckets :: Connection -> Credentials -> IO [BucketInfo] Source #
List buckets owned by user
createBucket :: Connection -> Credentials -> BucketId -> Maybe Acl -> IO () Source #
Create bucket
deleteBucket :: Connection -> Credentials -> BucketId -> IO () Source #
Delete bucket
NOTE: Most S3 implementations require the bucket to be empty before it can be deleted. See documentation of listObjectsFold
for a code example deleting a non-empty bucket.
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | prefix |
-> Maybe Char | delimiter |
-> IO ([ObjMetaInfo], [ObjKey]) | (objects, prefixes) |
List all objects in a bucket
This operation may cause multiple HTTP requests to be issued
See also listObjectsChunk
and listObjectsFold
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | prefix |
-> Maybe Char | delimiter |
-> Word16 | max number of keys per iteration |
-> a | initial value of accumulator argument to folding function |
-> (a -> [ObjMetaInfo] -> [ObjKey] -> IO a) | folding function |
-> IO a | returns final value of accumulator value |
Convenient foldM
-like object listing operation
Here's an usage example for iterating over the list of objects in chunks of 100 objects and deleting those; and finally deleting the bucket:
destroyBucket conn creds bid = do listObjectsFold conn creds bid nullObjKey Nothing 100 () $ \() objs [] -> forM_ objs $ \omi -> deleteObject conn creds bid (omiKey omi) deleteBucket conn creds bid
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | prefix (use |
-> Maybe Char | delimiter |
-> ObjKey | marker (use |
-> Word16 | max-keys (set |
-> IO (ObjKey, [ObjMetaInfo], [ObjKey]) | (next-marker, objects, prefixes) |
Primitive operation for list objects
This operation corresponds to a single HTTP service request
The listObjectsChunk
and listObjects
operations build on this primitive building block.
Operations on Objects
Object keys
The name for a key is a non-empty sequence of Unicode characters whose UTF-8 encoding is at most 1024 bytes long.
See also remarks in s3cfgEncodingUrl
about permissible code-points.
See also AWS S3's documentation on "Object Key and Metadata"
isNullObjKey :: ObjKey -> Bool Source #
Test whether ObjKey
is the nullObjKey
nullObjKey :: ObjKey Source #
Represents the null (or empty) ObjKey
Object metadata
data ObjMetaInfo Source #
Object Metadata
Instances
Content-type
Denotes an ETag
ETag !ShortByteString | |
ETagMD5 !MD5Val | This constructor will be used if the ETag looks like a proper MD5 based ETag |
Instances
Eq ETag Source # | |
Ord ETag Source # | |
Show ETag Source # | |
Generic ETag Source # | |
NFData ETag Source # | |
Defined in Network.S3.Types | |
Hashable ETag Source # | |
Defined in Network.S3.Types | |
type Rep ETag Source # | |
Defined in Network.S3.Types type Rep ETag = D1 (MetaData "ETag" "Network.S3.Types" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) (C1 (MetaCons "ETag" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ShortByteString)) :+: C1 (MetaCons "ETagMD5" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 MD5Val))) |
MD5 hashes
MD5 Hash
md5hash :: ByteString -> MD5Val Source #
Compute MD5 hash
md5hex :: MD5Val -> ByteString Source #
Hex-encode MD5 digest value
md5ToSBS :: MD5Val -> ShortByteString Source #
Extract MD5 digest value
md5FromSBS :: ShortByteString -> Maybe MD5Val Source #
Construct MD5 digest value from 16 octets
Operations
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | Object key |
-> ByteString | Object payload data |
-> CType |
|
-> Maybe Acl | |
-> IO ETag |
PUT
Object
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | |
-> (BucketId, ObjKey) | source object to copy |
-> Maybe Acl | |
-> IO ETag |
Copy Object
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | Object key |
-> IO (ETag, CType, ByteString) |
GET
Object
deleteObject :: Connection -> Credentials -> BucketId -> ObjKey -> IO () Source #
DELETE
Object
Conditional operations
Conditional Request
Note that S3 server implementations vary in their support for conditional requests
IfExists | If-Match: * |
IfNotExists | If-None-Match: * |
IfMatch !ETag | If-Match: ... |
IfNotMatch !ETag | If-None-Match: ... |
Instances
Eq Condition Source # | |
Show Condition Source # | |
Generic Condition Source # | |
NFData Condition Source # | |
Defined in Network.S3.Types | |
type Rep Condition Source # | |
Defined in Network.S3.Types type Rep Condition = D1 (MetaData "Condition" "Network.S3.Types" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) ((C1 (MetaCons "IfExists" PrefixI False) (U1 :: Type -> Type) :+: C1 (MetaCons "IfNotExists" PrefixI False) (U1 :: Type -> Type)) :+: (C1 (MetaCons "IfMatch" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ETag)) :+: C1 (MetaCons "IfNotMatch" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ETag)))) |
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | Object key |
-> ByteString | Object payload data |
-> CType |
|
-> Maybe Acl | |
-> Condition | |
-> IO (Maybe ETag) |
:: Connection | |
-> Credentials | |
-> BucketId | |
-> ObjKey | Object key |
-> Condition | |
-> IO (Maybe (ETag, CType, ByteString)) |
deleteObjectCond :: Connection -> Credentials -> BucketId -> ObjKey -> Condition -> IO Bool Source #
Errors
S3-level errors
AccessDenied | |
BucketAlreadyExists | |
BucketAlreadyOwnedByYou | |
BucketNotEmpty | |
MalformedXML | |
NoSuchBucket | |
NoSuchKey | |
InvalidArgument | |
InvalidDigest | |
SignatureDoesNotMatch | |
UnknownError !ShortText |
Instances
data ProtocolError Source #
Protocol-level errors and exceptions
ProtocolInconsistency String | |
HttpFailure !SomeException | |
UnexpectedResponse !Int !ShortByteString !ShortByteString ByteString |
Instances
Authentication
data Credentials Source #
S3 Credentials
We use memory pinned ByteString
s because we don't want to have the credential data copied around more than necessary.
Credentials | |
|
Instances
Eq Credentials Source # | |
Defined in Network.S3.Types (==) :: Credentials -> Credentials -> Bool # (/=) :: Credentials -> Credentials -> Bool # | |
Show Credentials Source # | |
Defined in Network.S3.Types showsPrec :: Int -> Credentials -> ShowS # show :: Credentials -> String # showList :: [Credentials] -> ShowS # | |
Generic Credentials Source # | |
Defined in Network.S3.Types type Rep Credentials :: Type -> Type # from :: Credentials -> Rep Credentials x # to :: Rep Credentials x -> Credentials # | |
NFData Credentials Source # | |
Defined in Network.S3.Types rnf :: Credentials -> () # | |
type Rep Credentials Source # | |
Defined in Network.S3.Types type Rep Credentials = D1 (MetaData "Credentials" "Network.S3.Types" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) (C1 (MetaCons "Credentials" PrefixI True) (S1 (MetaSel (Just "s3AccessKey") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ByteString) :*: S1 (MetaSel (Just "s3SecretKey") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ByteString))) |
noCredentials :: Credentials Source #
Anonymous access
Connection handling
Configure S3 endpoint
S3Cfg | |
|
Instances
Show S3Cfg Source # | |
Generic S3Cfg Source # | |
NFData S3Cfg Source # | |
Defined in Network.S3.Types | |
type Rep S3Cfg Source # | |
Defined in Network.S3.Types type Rep S3Cfg = D1 (MetaData "S3Cfg" "Network.S3.Types" "S3-0.1.0.0-ICJYI1Ni7n55Gr22u6JgTL" False) (C1 (MetaCons "S3Cfg" PrefixI True) ((S1 (MetaSel (Just "s3cfgBaseUrl") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 URL) :*: S1 (MetaSel (Just "s3cfgRegion") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 ByteString)) :*: (S1 (MetaSel (Just "s3cfgSigVersion") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 SignatureVersion) :*: (S1 (MetaSel (Just "s3cfgEncodingUrl") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 Bool) :*: S1 (MetaSel (Just "s3cfgDebug") NoSourceUnpackedness SourceStrict DecidedStrict) (Rec0 Bool))))) |
defaultS3Cfg :: S3Cfg Source #
Default S3Cfg
value with recommended/default settings, i.e.
>>>
defaultS3Cfg
S3Cfg {s3cfgBaseUrl = "", s3cfgRegion = "us-east-1", s3cfgSigVersion = SignatureV4, s3cfgEncodingUrl = False, s3cfgDebug = False}
NOTE: At the very least you have to override the s3cfgBaseUrl
field.
data SignatureVersion Source #
Denotes version of the S3 request signing algorithm
SignatureV2 | Legacy HMAC-SHA1/MD5 based signing algorithm |
SignatureV4 | Current HMAC-SHA256 based signing algorithm (recommended) |
Instances
Eq SignatureVersion Source # | |
Defined in Network.S3.Types (==) :: SignatureVersion -> SignatureVersion -> Bool # (/=) :: SignatureVersion -> SignatureVersion -> Bool # | |
Show SignatureVersion Source # | |
Defined in Network.S3.Types showsPrec :: Int -> SignatureVersion -> ShowS # show :: SignatureVersion -> String # showList :: [SignatureVersion] -> ShowS # | |
Generic SignatureVersion Source # | |
Defined in Network.S3.Types type Rep SignatureVersion :: Type -> Type # from :: SignatureVersion -> Rep SignatureVersion x # to :: Rep SignatureVersion x -> SignatureVersion # | |
NFData SignatureVersion Source # | |
Defined in Network.S3.Types rnf :: SignatureVersion -> () # | |
type Rep SignatureVersion Source # | |
data Connection Source #
Represents a single-threaded HTTP channel to the S3 service
withConnection :: S3Cfg -> (Connection -> IO a) -> IO a Source #
Simple single-connection bracket
style combinator over connect
and close
If you need resource pool management you can use connect
in combination with packages such as resource-pool.