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 +29/−1
- amazonka.cabal +2/−3
- src/Control/Monad/Trans/AWS.hs +64/−47
- src/Network/AWS.hs +26/−13
- src/Network/AWS/Internal/Body.hs +74/−30
- src/Network/AWS/Internal/HTTP.hs +1/−1
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