diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
diff --git a/amazonka.cabal b/amazonka.cabal
--- a/amazonka.cabal
+++ b/amazonka.cabal
@@ -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
diff --git a/src/Control/Monad/Trans/AWS.hs b/src/Control/Monad/Trans/AWS.hs
--- a/src/Control/Monad/Trans/AWS.hs
+++ b/src/Control/Monad/Trans/AWS.hs
@@ -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.
diff --git a/src/Network/AWS.hs b/src/Network/AWS.hs
--- a/src/Network/AWS.hs
+++ b/src/Network/AWS.hs
@@ -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.
diff --git a/src/Network/AWS/Internal/Body.hs b/src/Network/AWS/Internal/Body.hs
--- a/src/Network/AWS/Internal/Body.hs
+++ b/src/Network/AWS/Internal/Body.hs
@@ -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
 
diff --git a/src/Network/AWS/Internal/HTTP.hs b/src/Network/AWS/Internal/HTTP.hs
--- a/src/Network/AWS/Internal/HTTP.hs
+++ b/src/Network/AWS/Internal/HTTP.hs
@@ -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
