diff --git a/Network/HTTP/Enumerator.hs b/Network/HTTP/Enumerator.hs
--- a/Network/HTTP/Enumerator.hs
+++ b/Network/HTTP/Enumerator.hs
@@ -110,6 +110,7 @@
     ( Iteratee (..), Stream (..), catchError, throwError
     , yield, Step (..), Enumeratee, ($$), joinI, Enumerator, run_
     , returnI, (>==>), (>>==), continue, checkDone, enumEOF
+    , (=$)
     )
 import qualified Data.Enumerator.List as EL
 import Network.HTTP.Enumerator.HttpParser
@@ -140,6 +141,7 @@
 import Blaze.ByteString.Builder (toByteString)
 import Data.Maybe (fromMaybe)
 import Data.Default (Default (def))
+import Numeric (showHex)
 #if !MIN_VERSION_base(4,3,0)
 import GHC.IO.Handle.Types
 import System.IO                (hWaitForInput, hIsEOF)
@@ -400,8 +402,8 @@
      -> (W.Status -> W.ResponseHeaders -> Iteratee S.ByteString m a)
      -> Manager
      -> Iteratee S.ByteString m a
-http Request {..} bodyStep m = do
-    withConn m connhost connport requestEnum $$ go
+http req@(Request {..}) bodyStep m =
+    withConn m connhost connport requestEnum $$ getResponse req bodyStep
   where
     (useProxy, connhost, connport) =
         case proxy of
@@ -455,36 +457,54 @@
                 `mappend` Blaze.fromByteString "\r\n")
             `mappend` Blaze.fromByteString "\r\n"
     requestEnum = enumSingle requestHeaders' >==> bodyEnum
-    go = do
-        ((_, sc, sm), hs) <- iterHeaders
-        let s = W.Status sc sm
-        let hs' = map (first CI.mk) hs
-        let mcl = lookup "content-length" hs'
-        let body' x =
-                if not rawBody && ("transfer-encoding", "chunked") `elem` hs'
-                    then joinI $ chunkedEnumeratee $$ x
-                    else case mcl >>= readMay . S8.unpack of
-                        Just len -> joinI $ takeLBS len $$ x
-                        Nothing -> x
-        let decompresser x =
-                if not rawBody
-                        && ("content-encoding", "gzip") `elem` hs'
-                        && decompress (fromMaybe "" $ lookup "content-type" hs')
-                    then joinI $ Z.ungzip x
-                    else returnI x
-        -- RFC 2616 section 4.4_1 defines responses that must not include a body
-        res <-
-            if method == "HEAD" || sc == 204 -- No Content
-                                || sc == 304 -- Not Modified
-                                || (sc < 200 && sc >= 100)
-                then enumEOF $$ bodyStep s hs'
-                else body' $ decompresser $$ do
-                        x <- bodyStep s hs'
-                        flushStream
-                        return x
-        let toPut = Just "close" /= lookup "connection" hs'
-        return (toPut, res)
 
+getResponse :: MonadIO m
+            => Request m
+            -> (W.Status -> [W.Header] -> Iteratee S8.ByteString m a)
+            -> Iteratee S8.ByteString m (Bool, a)
+getResponse Request {..} bodyStep = do
+    ((_, sc, sm), hs) <- iterHeaders
+    let s = W.Status sc sm
+    let hs' = map (first CI.mk) hs
+    let mcl = lookup "content-length" hs'
+    let body' =
+            case (rawBody, ("transfer-encoding", "chunked") `elem` hs') of
+                (False, True) -> (chunkedEnumeratee =$)
+                (True , True) -> (chunkedTerminator =$)
+                (_    , False) -> case mcl >>= readMay . S8.unpack of
+                                      Just len -> (takeLBS len =$)
+                                      Nothing  -> id
+    let decompresser =
+            if needsGunzip hs'
+                then (Z.ungzip =$)
+                else id
+    -- RFC 2616 section 4.4_1 defines responses that must not include a body
+    res <-
+        if hasNoBody method sc
+            then enumEOF $$ bodyStep s hs'
+            else body' $ decompresser $ do
+                    x <- bodyStep s hs'
+                    flushStream
+                    return x
+
+    -- should we put this connection back into the connection manager?
+    let toPut = Just "close" /= lookup "connection" hs'
+    return (toPut, res)
+  where
+    hasNoBody :: S8.ByteString -- ^ request method
+              -> Int -- ^ status code
+              -> Bool
+    hasNoBody "HEAD" _ = True
+    hasNoBody _ 204 = True
+    hasNoBody _ 304 = True
+    hasNoBody _ i = 100 <= i && i < 200
+
+    needsGunzip :: [W.Header] -> Bool
+    needsGunzip hs' =
+            not rawBody
+         && ("content-encoding", "gzip") `elem` hs'
+         && decompress (fromMaybe "" $ lookup "content-type" hs')
+
 flushStream :: Monad m => Iteratee a m ()
 flushStream = do
     x <- EL.head
@@ -502,6 +522,28 @@
             catchParser "End of chunk newline" iterNewline
             chunkedEnumeratee k'
 chunkedEnumeratee step = return step
+
+chunkedTerminator :: MonadIO m => Enumeratee S.ByteString S.ByteString m a
+chunkedTerminator (Continue k) = do
+    len <- catchParser "Chunk header" iterChunkHeader
+    k' <- sendCont k $ S8.pack $ showHex len "\r\n"
+    if len == 0
+        then return k'
+        else do
+            step <- takeLBS len k'
+            catchParser "End of chunk newline" iterNewline
+            case step of
+                Continue k'' -> do
+                    k''' <- sendCont k'' "\r\n"
+                    chunkedTerminator k'''
+                _ -> return step
+chunkedTerminator step = return step
+
+sendCont :: Monad m
+         => (Stream S8.ByteString -> Iteratee S8.ByteString m a)
+         -> S8.ByteString
+         -> Iteratee S8.ByteString m (Step S8.ByteString m a)
+sendCont k bs = lift $ runIteratee $ k $ Chunks [bs]
 
 chunkIt :: Monad m => Enumeratee Blaze.Builder Blaze.Builder m a
 chunkIt = checkDone $ continue . step
diff --git a/http-enumerator.cabal b/http-enumerator.cabal
--- a/http-enumerator.cabal
+++ b/http-enumerator.cabal
@@ -1,5 +1,5 @@
 name:            http-enumerator
-version:         0.7.1.2
+version:         0.7.1.3
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
