packages feed

amazonka 1.3.1 → 1.3.2

raw patch · 6 files changed

+196/−95 lines, 6 filesdep −http-clientdep ~amazonka-corePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: http-client

Dependency ranges changed: amazonka-core

API changes (from Hackage documentation)

- Control.Monad.Trans.AWS: data AWST m a
- Control.Monad.Trans.AWS: instance Alternative m => Alternative (AWST m)
- Control.Monad.Trans.AWS: instance Applicative m => Applicative (AWST m)
- Control.Monad.Trans.AWS: instance Functor m => Functor (AWST m)
- Control.Monad.Trans.AWS: instance MFunctor AWST
- Control.Monad.Trans.AWS: instance Monad m => Monad (AWST m)
- Control.Monad.Trans.AWS: instance Monad m => MonadReader Env (AWST m)
- Control.Monad.Trans.AWS: instance MonadActive m => MonadActive (AWST m)
- Control.Monad.Trans.AWS: instance MonadBase b m => MonadBase b (AWST m)
- Control.Monad.Trans.AWS: instance MonadBaseControl b m => MonadBaseControl b (AWST m)
- Control.Monad.Trans.AWS: instance MonadCatch m => MonadCatch (AWST m)
- Control.Monad.Trans.AWS: instance MonadError e m => MonadError e (AWST m)
- Control.Monad.Trans.AWS: instance MonadIO m => MonadIO (AWST m)
- Control.Monad.Trans.AWS: instance MonadMask m => MonadMask (AWST m)
- Control.Monad.Trans.AWS: instance MonadPlus m => MonadPlus (AWST m)
- Control.Monad.Trans.AWS: instance MonadResource m => MonadResource (AWST m)
- Control.Monad.Trans.AWS: instance MonadState s m => MonadState s (AWST m)
- Control.Monad.Trans.AWS: instance MonadThrow m => MonadThrow (AWST m)
- Control.Monad.Trans.AWS: instance MonadTrans AWST
- Control.Monad.Trans.AWS: instance MonadTransControl AWST
- Control.Monad.Trans.AWS: instance MonadWriter w m => MonadWriter w (AWST m)
- Control.Monad.Trans.AWS: sourceBody :: Digest SHA256 -> Int64 -> Source (ResourceT IO) ByteString -> RqBody
- Control.Monad.Trans.AWS: sourceFile :: Digest SHA256 -> Int64 -> FilePath -> RqBody
- Control.Monad.Trans.AWS: sourceFileIO :: MonadIO m => FilePath -> m RqBody
- Control.Monad.Trans.AWS: sourceHandle :: Digest SHA256 -> Int64 -> Handle -> RqBody
- Network.AWS: sourceBody :: Digest SHA256 -> Int64 -> Source (ResourceT IO) ByteString -> RqBody
- Network.AWS: sourceFile :: Digest SHA256 -> Int64 -> FilePath -> RqBody
- Network.AWS: sourceFileIO :: MonadIO m => FilePath -> m RqBody
- Network.AWS: sourceHandle :: Digest SHA256 -> Int64 -> Handle -> RqBody
+ Control.Monad.Trans.AWS: ChunkSize :: Int -> ChunkSize
+ Control.Monad.Trans.AWS: chunkedFile :: MonadIO m => ChunkSize -> FilePath -> m RqBody
+ Control.Monad.Trans.AWS: class ToHashedBody a
+ Control.Monad.Trans.AWS: data AWST' r m a
+ Control.Monad.Trans.AWS: data ChunkedBody :: *
+ Control.Monad.Trans.AWS: data HashedBody :: *
+ Control.Monad.Trans.AWS: defaultChunkSize :: ChunkSize
+ Control.Monad.Trans.AWS: hashedBody :: Digest SHA256 -> Integer -> Source (ResourceT IO) ByteString -> HashedBody
+ Control.Monad.Trans.AWS: hashedFile :: MonadIO m => FilePath -> m HashedBody
+ Control.Monad.Trans.AWS: instance Alternative m => Alternative (AWST' r m)
+ Control.Monad.Trans.AWS: instance Applicative m => Applicative (AWST' r m)
+ Control.Monad.Trans.AWS: instance Functor m => Functor (AWST' r m)
+ Control.Monad.Trans.AWS: instance MFunctor (AWST' r)
+ Control.Monad.Trans.AWS: instance Monad m => Monad (AWST' r m)
+ Control.Monad.Trans.AWS: instance Monad m => MonadReader r (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadActive m => MonadActive (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadBase b m => MonadBase b (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadBaseControl b m => MonadBaseControl b (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadCatch m => MonadCatch (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadError e m => MonadError e (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadIO m => MonadIO (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadMask m => MonadMask (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadPlus m => MonadPlus (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadResource m => MonadResource (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadState s m => MonadState s (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadThrow m => MonadThrow (AWST' r m)
+ Control.Monad.Trans.AWS: instance MonadTrans (AWST' r)
+ Control.Monad.Trans.AWS: instance MonadTransControl (AWST' r)
+ Control.Monad.Trans.AWS: instance MonadWriter w m => MonadWriter w (AWST' r m)
+ Control.Monad.Trans.AWS: newtype ChunkSize :: *
+ Control.Monad.Trans.AWS: toHashed :: ToHashedBody a => a -> HashedBody
+ Control.Monad.Trans.AWS: type AWST = AWST' Env
+ Control.Monad.Trans.AWS: unsafeChunkedBody :: ChunkSize -> Integer -> Source (ResourceT IO) ByteString -> RqBody
+ Network.AWS: ChunkSize :: Int -> ChunkSize
+ Network.AWS: chunkedFile :: MonadIO m => ChunkSize -> FilePath -> m RqBody
+ Network.AWS: class ToHashedBody a
+ Network.AWS: data ChunkedBody :: *
+ Network.AWS: data HashedBody :: *
+ Network.AWS: defaultChunkSize :: ChunkSize
+ Network.AWS: hashedBody :: Digest SHA256 -> Integer -> Source (ResourceT IO) ByteString -> HashedBody
+ Network.AWS: hashedFile :: MonadIO m => FilePath -> m HashedBody
+ Network.AWS: newtype ChunkSize :: *
+ Network.AWS: toHashed :: ToHashedBody a => a -> HashedBody
+ Network.AWS: unsafeChunkedBody :: ChunkSize -> Integer -> Source (ResourceT IO) ByteString -> RqBody
- Control.Monad.Trans.AWS: getFileSize :: MonadIO m => FilePath -> m Int64
+ Control.Monad.Trans.AWS: getFileSize :: MonadIO m => FilePath -> m Integer
- Control.Monad.Trans.AWS: runAWST :: HasEnv r => r -> AWST m a -> m a
+ Control.Monad.Trans.AWS: runAWST :: HasEnv r => r -> AWST' r m a -> m a
- Network.AWS: getFileSize :: MonadIO m => FilePath -> m Int64
+ Network.AWS: getFileSize :: MonadIO m => FilePath -> m Integer

Files

CHANGELOG.md view
@@ -1,6 +1,33 @@ # Change Log +## [1.3.2](https://github.com/brendanhay/amazonka/tree/1.3.2)+Released: **18 September, 2015**, Compare: [1.3.1](https://github.com/brendanhay/amazonka/compare/1.3.1...1.3.2) +### Fixed++- Ensure opqaue JSON bodies are handled correctly. [\#224](https://github.com/brendanhay/amazonka/issues/224) [\#226](https://github.com/brendanhay/amazonka/issues/226)++### Updated Service Definitions++- EC2: Documentation updates.+- EFS: Documentation updates.+- Route53: Inverted, Measured Latency, and Child Health Check updates.+- CloudWatchLogs+    * `InvalidOperationException` error matcher added.+    * `DescribeExportTasks` operation added+    * `CreateExportTask` operation added+    * `CancelExportTask` operation added+    * `ExportTask`, `ExportTaskExecutionInfo`, `ExportTaskStatus` types added.+- S3+    * Infrequent access storage tier updates.+    * `GetBucketLifecycle` operation removed (deprecated).+    * `PutBucketLifecycle` operation removed (deprecated).+    * `Rule` product removed (deprecated).+    * `GetbucketLifecycleConfiguration` operation added.+    * `PutBucketLifecycleConfiguration` operation added.+    * `BucketLifecycleConfiguration` product added.+    * `LifecycleRule` product added.+ ## [1.3.1](https://github.com/brendanhay/amazonka/tree/1.3.1) Released: **09 September, 2015**, Compare: [1.3.0](https://github.com/brendanhay/amazonka/compare/1.3.0...1.3.1) @@ -9,7 +36,7 @@ - Fix S3 ListObject pagination regression. [\#218](https://github.com/brendanhay/amazonka/issues/218) - Corrected IS08601 timezone de/serialisation. [\#217](https://github.com/brendanhay/amazonka/issues/217) - Remove required EC2 VPC `isDefault` member. [\#214](https://github.com/brendanhay/amazonka/issues/214)-- Correctly named MachineLearning CreateDataSourceFromS3. [4805074]+- Correctly named MachineLearning CreateDataSourceFromS3. [4805074](https://github.com/brendanhay/amazonka/commit/4805074)  ### Updated Service Definitions @@ -22,6 +49,7 @@ - Kinesis - DataPipeline - EFS: Namespace rename from ElasticFileSystem -> EFS.+  ## [1.3.0](https://github.com/brendanhay/amazonka/tree/1.3.0) Released: **03 September, 2015**, Compare: [1.2.0.2](https://github.com/brendanhay/amazonka/compare/1.2.0.2...1.3.0)
amazonka.cabal view
@@ -1,5 +1,5 @@ name:                  amazonka-version:               1.3.1+version:               1.3.2 synopsis:              Comprehensive Amazon Web Services SDK homepage:              https://github.com/brendanhay/amazonka bug-reports:           https://github.com/brendanhay/amazonka/issues@@ -55,14 +55,13 @@         , Network.AWS.Internal.Logger      build-depends:-          amazonka-core       == 1.3.1.*+          amazonka-core       == 1.3.2.*         , base                >= 4.7     && < 5         , bytestring          >= 0.9         , conduit             >= 1.1         , conduit-extra       >= 1.1         , directory           >= 1.2         , exceptions          >= 0.6-        , http-client         >= 0.4.9         , http-conduit        >= 2.1.4         , ini                 >= 0.2         , lens                >= 4.4
src/Control/Monad/Trans/AWS.hs view
@@ -30,6 +30,7 @@     (     -- * Running AWS Actions       AWST+    , AWST'     , runAWST     , AWSConstraint @@ -77,11 +78,16 @@     -- $streaming      -- *** Request Bodies+    , ToHashedBody (..)+    , hashedFile+    , hashedBody++    -- *** Chunked Request Bodies     , ToBody       (..)-    , sourceBody-    , sourceHandle-    , sourceFile-    , sourceFileIO+    , ChunkSize    (..)+    , defaultChunkSize+    , chunkedFile+    , unsafeChunkedBody      -- *** Response Bodies     , sinkBody@@ -134,11 +140,13 @@     , setEndpoint      -- * Re-exported Types-    , RqBody-    , RsBody     , module Network.AWS.Types     , module Network.AWS.Waiter     , module Network.AWS.Pager+    , RqBody+    , HashedBody+    , ChunkedBody+    , RsBody      -- * runResourceT     , runResourceT@@ -172,8 +180,9 @@ import           Network.AWS.Types            hiding (LogLevel (..)) import           Network.AWS.Waiter           (Wait) --- | The 'AWST' transformer.-newtype AWST m a = AWST { unAWST :: ReaderT Env m a }+type AWST = AWST' Env++newtype AWST' r m a = AWST' { unAWST :: ReaderT r m a }     deriving         ( Functor         , Applicative@@ -181,65 +190,67 @@         , Monad         , MonadPlus         , MonadIO-        , MonadReader Env         , MonadActive+        , MonadTrans         ) -instance MonadThrow m => MonadThrow (AWST m) where+instance MonadThrow m => MonadThrow (AWST' r m) where     throwM = lift . throwM -instance MonadCatch m => MonadCatch (AWST m) where-    catch (AWST m) f = AWST (catch m (unAWST . f))+instance MonadCatch m => MonadCatch (AWST' r m) where+    catch (AWST' m) f = AWST' (catch m (unAWST . f)) -instance MonadMask m => MonadMask (AWST m) where-    mask a = AWST $ mask $ \u ->-        unAWST $ a (AWST . u . unAWST)+instance MonadMask m => MonadMask (AWST' r m) where+    mask a = AWST' $ mask $ \u ->+        unAWST $ a (AWST' . u . unAWST) -    uninterruptibleMask a = AWST $ uninterruptibleMask $ \u ->-        unAWST $ a (AWST . u . unAWST)+    uninterruptibleMask a = AWST' $ uninterruptibleMask $ \u ->+        unAWST $ a (AWST' . u . unAWST) -instance MonadBase b m => MonadBase b (AWST m) where+instance MonadBase b m => MonadBase b (AWST' r m) where     liftBase = liftBaseDefault -instance MonadTransControl AWST where-    type StT AWST a = StT (ReaderT Env) a+instance MonadTransControl (AWST' r) where+    type StT (AWST' r) a = StT (ReaderT r) a -    liftWith = defaultLiftWith AWST unAWST-    restoreT = defaultRestoreT AWST+    liftWith = defaultLiftWith AWST' unAWST+    restoreT = defaultRestoreT AWST' -instance MonadBaseControl b m => MonadBaseControl b (AWST m) where-    type StM (AWST m) a = ComposeSt AWST m a+instance MonadBaseControl b m => MonadBaseControl b (AWST' r m) where+    type StM (AWST' r m) a = ComposeSt (AWST' r) m a      liftBaseWith = defaultLiftBaseWith     restoreM     = defaultRestoreM -instance MonadTrans AWST where-    lift = AWST . lift--instance MonadResource m => MonadResource (AWST m) where+instance MonadResource m => MonadResource (AWST' r m) where     liftResourceT = lift . liftResourceT -instance MonadError e m => MonadError e (AWST m) where+instance MonadError e m => MonadError e (AWST' r m) where     throwError     = lift . throwError-    catchError m f = AWST (unAWST m `catchError` (unAWST . f))+    catchError m f = AWST' (unAWST m `catchError` (unAWST . f)) -instance MonadState s m => MonadState s (AWST m) where-    get = lift get-    put = lift . put+instance Monad m => MonadReader r (AWST' r m) where+    ask     = AWST' ask+    local f = AWST' . local f . unAWST+    reader  = AWST' . reader -instance MonadWriter w m => MonadWriter w (AWST m) where+instance MonadWriter w m => MonadWriter w (AWST' r m) where     writer = lift . writer     tell   = lift . tell-    listen = AWST . listen . unAWST-    pass   = AWST . pass   . unAWST+    listen = AWST' . listen . unAWST+    pass   = AWST' . pass   . unAWST -instance MFunctor AWST where-    hoist nat = AWST . hoist nat . unAWST+instance MonadState s m => MonadState s (AWST' r m) where+    get = lift get+    put = lift . put --- | Run an 'AWST' action with the specified 'HasEnv' environment.-runAWST :: HasEnv r => r -> AWST m a -> m a-runAWST r (AWST m) = runReaderT m (r ^. environment)+instance MFunctor (AWST' r) where+    hoist nat = AWST' . hoist nat . unAWST +-- | Run an 'AWST' action with the specified environment.+runAWST :: HasEnv r => r -> AWST' r m a -> m a+runAWST r (AWST' m) = runReaderT m r+ -- | An alias for the constraints required to send requests, -- which 'AWST' implicitly fulfils. type AWSConstraint r m =@@ -449,13 +460,19 @@ -}  {- $streaming-Streaming request bodies (such as 'PutObject') require a precomputed-'SHA256' for signing purposes.-The 'ToBody' typeclass has instances available to construct a 'RqBody',-automatically calculating the hash as needed for types such as 'Text' and 'ByteString'.+Streaming comes in two flavours. 'HashedBody' represents a request+that requires a precomputed 'SHA256' hash, or a 'ChunkedBody' type for those services+that can perform incremental signing and do not require the entire payload to+be hashed (such as 'S3'). The type signatures for request smart constructors+advertise which respective body type is required, denoting the underlying signing+capabilities. -For reading files and handles, functions such 'sourceFileIO' or 'sourceHandle'-can be used.+'ToHashedBody' and 'ToBody' typeclass instances are available to construct the+streaming bodies, automatically calculating any hash or size as needed for types+such as 'Text', 'ByteString', or Aeson's 'Value' type. To read files and other+'IO' primitives, functions such as 'hashedFile', 'chunkedFile', or 'hashedBody'+should be used.+ For responses that contain streaming bodies (such as 'GetObject'), you can use 'sinkBody' to connect the response body to a <http://hackage.haskell.org/package/conduit conduit> compatible sink.
src/Network/AWS.hs view
@@ -75,11 +75,16 @@     -- $streaming      -- *** Request Bodies+    , ToHashedBody (..)+    , hashedFile+    , hashedBody++    -- *** Chunked Request Bodies     , ToBody       (..)-    , sourceBody-    , sourceHandle-    , sourceFile-    , sourceFileIO+    , ChunkSize    (..)+    , defaultChunkSize+    , chunkedFile+    , unsafeChunkedBody      -- *** Response Bodies     , sinkBody@@ -131,11 +136,13 @@     , AWST.setEndpoint      -- * Re-exported Types-    , RqBody-    , RsBody     , module Network.AWS.Types     , module Network.AWS.Waiter     , module Network.AWS.Pager+    , RqBody+    , HashedBody+    , ChunkedBody+    , RsBody      -- * runResourceT     , runResourceT@@ -215,7 +222,7 @@ -- -- /See:/ 'AWST.runAWST', 'runResourceT'. runAWS :: (MonadResource m, HasEnv r) => r -> AWS a -> m a-runAWS e = liftResourceT . AWST.runAWST e+runAWS e = liftResourceT . AWST.runAWST (e ^. environment)  -- | Scope an action such that all requests belonging to the supplied service -- will use this configuration instead of the default.@@ -425,13 +432,19 @@ -}  {- $streaming-Streaming request bodies (such as 'PutObject') require a precomputed-'SHA256' for signing purposes.-The 'ToBody' typeclass has instances available to construct a 'RqBody',-automatically calculating the hash as needed for types such as 'Text' and 'ByteString'.+Streaming comes in two flavours. 'HashedBody' represents a request+that requires a precomputed 'SHA256' hash, or a 'ChunkedBody' type for those services+that can perform incremental signing and do not require the entire payload to+be hashed (such as 'S3'). The type signatures for request smart constructors+advertise which respective body type is required, denoting the underlying signing+capabilities. -For reading files and handles, functions such 'sourceFileIO' or 'sourceHandle'-can be used.+'ToHashedBody' and 'ToBody' typeclass instances are available to construct the+streaming bodies, automatically calculating any hash or size as needed for types+such as 'Text', 'ByteString', or Aeson's 'Value' type. To read files and other+'IO' primitives, functions such as 'hashedFile', 'chunkedFile', or 'hashedBody'+should be used.+ For responses that contain streaming bodies (such as 'GetObject'), you can use 'sinkBody' to connect the response body to a <http://hackage.haskell.org/package/conduit conduit> compatible sink.
src/Network/AWS/Internal/Body.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+ -- | -- Module      : Network.AWS.Internal.Body -- Copyright   : (c) 2013-2015 Brendan Hay@@ -13,56 +15,98 @@ import           Control.Monad.IO.Class import           Control.Monad.Morph import           Control.Monad.Trans.Resource+import qualified Data.ByteString              as BS import           Data.Conduit import qualified Data.Conduit.Binary          as Conduit-import           Data.Int import           Network.AWS.Prelude-import qualified Network.HTTP.Client          as Client-import           Network.HTTP.Conduit import           System.IO  import           Prelude --- | Construct a 'RqBody' from a source, manually specifying the--- SHA256 hash and file size.-sourceBody :: Digest SHA256-           -> Int64-           -> Source (ResourceT IO) ByteString-           -> RqBody-sourceBody h n = RqBody h . requestBodySource n---- | Construct a 'RqBody' from a 'Handle', manually specifying the--- SHA256 hash and file size.-sourceHandle :: Digest SHA256 -> Int64 -> Handle -> RqBody-sourceHandle h n = sourceBody h n . Conduit.sourceHandle+-- | Convenience function for obtaining the size of a file.+getFileSize :: MonadIO m => FilePath -> m Integer+getFileSize f = liftIO (withBinaryFile f ReadMode hFileSize) --- | Construct a 'RqBody' from a 'FilePath', manually specifying the--- SHA256 hash and file size.-sourceFile :: Digest SHA256 -> Int64 -> FilePath -> RqBody-sourceFile h n = sourceBody h n . Conduit.sourceFile+-- | Connect a 'Sink' to a response stream.+sinkBody :: MonadResource m => RsBody -> Sink ByteString m a -> m a+sinkBody (RsBody s) sink = hoist liftResourceT s $$+- sink --- | Construct a 'RqBody' from a 'FilePath', calculating the SHA256 hash+-- | Construct a 'HashedBody' from a 'FilePath', calculating the 'SHA256' hash -- and file size. -- -- /Note:/ While this function will perform in constant space, it will enumerate the -- entirety of the file contents _twice_. Firstly to calculate the SHA256 and -- lastly to stream the contents to the socket during sending.-sourceFileIO :: MonadIO m => FilePath -> m RqBody-sourceFileIO f = liftIO $-    RqBody <$> runResourceT (Conduit.sourceFile f $$ sinkSHA256)-           <*> Client.streamFile f+--+-- /See:/ 'ToHashedBody'.+hashedFile :: MonadIO m => FilePath -> m HashedBody+hashedFile f = liftIO $ HashedStream+    <$> runResourceT (Conduit.sourceFile f $$ sinkSHA256)+    <*> getFileSize f+    <*> pure (Conduit.sourceFile f) --- | Convenience function for obtaining the size of a file.-getFileSize :: MonadIO m => FilePath -> m Int64-getFileSize f = liftIO $ fromIntegral `liftM` withBinaryFile f ReadMode hFileSize+-- | Construct a 'HashedBody' from a source, manually specifying the+-- 'SHA256' hash and file size.+--+-- /See:/ 'ToHashedBody'.+hashedBody :: Digest SHA256+           -> Integer+           -> Source (ResourceT IO) ByteString+           -> HashedBody+hashedBody h n = HashedStream h n --- | Connect a 'Sink' to a reponse body.-sinkBody :: MonadResource m => RsBody -> Sink ByteString m a -> m a-sinkBody (RsBody src) sink = hoist liftResourceT src $$+- sink+-- | Something something.+--+-- Will intelligently revert to 'HashedBody' if the file is smaller than the+-- specified 'ChunkSize'.+--+-- Add note about how it selects chunk size.+--+-- /See:/ 'ToBody'.+chunkedFile :: MonadIO m => ChunkSize -> FilePath -> m RqBody+chunkedFile c f = do+    n <- getFileSize f+    if n > toInteger c+        then return $ unsafeChunkedBody c n (sourceFileChunks c f)+        else Hashed `liftM` hashedFile f +-- | Something something.+--+-- Marked as unsafe because it does nothing to enforce the chunk size.+-- Typically for conduit 'IO' functions, it's whatever ByteString's+-- 'defaultBufferSize' is, around 32 KB. If the chunk size is less than 8 KB,+-- the request will error. 64 KB or higher chunk size is recommended for+-- performance reasons.+--+-- Note that it will always create a chunked body even if the request+-- is too small.+--+-- /See:/ 'ToBody'.+unsafeChunkedBody :: ChunkSize+                  -> Integer+                  -> Source (ResourceT IO) ByteString+                  -> RqBody+unsafeChunkedBody c n = Chunked . ChunkedBody c n++-- Uses hGet with a specific buffer size, instead of hGetSome.+sourceFileChunks :: MonadResource m+                 => ChunkSize+                 -> FilePath+                 -> Source m ByteString+sourceFileChunks (ChunkSize sz) f =+    bracketP (openBinaryFile f ReadMode) hClose go+  where+    go h = do+        bs <- liftIO (BS.hGet h sz)+        unless (BS.null bs) $ do+            yield bs+            go h++-- | Incrementally calculate a 'MD5' 'Digest'. sinkMD5 :: Monad m => Consumer ByteString m (Digest MD5) sinkMD5 = sinkHash +-- | Incrementally calculate a 'SHA256' 'Digest'. sinkSHA256 :: Monad m => Consumer ByteString m (Digest SHA256) sinkSHA256 = sinkHash 
src/Network/AWS/Internal/HTTP.hs view
@@ -154,7 +154,7 @@ retryStream :: Request a -> RetryPolicy retryStream x = RetryPolicy (const $ listToMaybe [0 | not p])   where-    !p = bodyStream (_rqBody x)+    !p = isStreaming (_rqBody x)  retryService :: Service -> RetryPolicy retryService s = limitRetries _retryAttempts <> RetryPolicy delay