diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,12 @@
 # Changelog for http-client
 
+## 0.6.3
+
+* Detect response body termination before reading an extra null chunk
+  when possible. This allows connections to be reused in some corner
+  cases. See
+  [#395](https://github.com/snoyberg/http-client/issues/395)
+
 ## 0.6.2
 
 * Add `shouldStripHeaderOnRedirect` option to `Request` [#300](https://github.com/snoyberg/http-client/issues/300)
diff --git a/Network/HTTP/Client/Body.hs b/Network/HTTP/Client/Body.hs
--- a/Network/HTTP/Client/Body.hs
+++ b/Network/HTTP/Client/Body.hs
@@ -8,7 +8,6 @@
     , brConsume
     , brEmpty
     , constBodyReader
-    , brAddCleanup
     , brReadSome
     , brRead
     ) where
@@ -61,12 +60,6 @@
             [] -> ([], S.empty)
             x:xs -> (xs, x)
 
-brAddCleanup :: IO () -> BodyReader -> BodyReader
-brAddCleanup cleanup brRead' = do
-    bs <- brRead'
-    when (S.null bs) cleanup
-    return bs
-
 -- | Strictly consume all remaining chunks of data from the stream.
 --
 -- Since 0.1.0
@@ -111,16 +104,25 @@
             Nothing -> start
             Just popper -> goPopper popper
 
-makeUnlimitedReader :: Connection -> IO BodyReader
-makeUnlimitedReader Connection {..} = do
+makeUnlimitedReader
+  :: IO () -- ^ cleanup
+  -> Connection
+  -> IO BodyReader
+makeUnlimitedReader cleanup Connection {..} = do
     icomplete <- newIORef False
     return $ do
         bs <- connectionRead
-        when (S.null bs) $ writeIORef icomplete True
+        when (S.null bs) $ do
+          writeIORef icomplete True
+          cleanup
         return bs
 
-makeLengthReader :: Int -> Connection -> IO BodyReader
-makeLengthReader count0 Connection {..} = do
+makeLengthReader
+  :: IO () -- ^ cleanup
+  -> Int
+  -> Connection
+  -> IO BodyReader
+makeLengthReader cleanup count0 Connection {..} = do
     icount <- newIORef count0
     return $ do
         count <- readIORef icount
@@ -134,20 +136,27 @@
                         let (x, y) = S.splitAt count bs
                         connectionUnread y
                         writeIORef icount (-1)
+                        cleanup
                         return x
                     EQ -> do
                         writeIORef icount (-1)
+                        cleanup
                         return bs
                     GT -> do
                         writeIORef icount (count - S.length bs)
                         return bs
 
-makeChunkedReader :: Bool -- ^ raw
-                  -> Connection
-                  -> IO BodyReader
-makeChunkedReader raw conn@Connection {..} = do
+makeChunkedReader
+  :: IO () -- ^ cleanup
+  -> Bool -- ^ raw
+  -> Connection
+  -> IO BodyReader
+makeChunkedReader cleanup raw conn@Connection {..} = do
     icount <- newIORef 0
-    return $ go icount
+    return $ do
+      bs <- go icount
+      when (S.null bs) cleanup
+      pure bs
   where
     go icount = do
         count0 <- readIORef icount
diff --git a/Network/HTTP/Client/Response.hs b/Network/HTTP/Client/Response.hs
--- a/Network/HTTP/Client/Response.hs
+++ b/Network/HTTP/Client/Response.hs
@@ -107,15 +107,14 @@
             else do
                 body1 <-
                     if isChunked
-                        then makeChunkedReader rawBody conn
+                        then makeChunkedReader (cleanup True) rawBody conn
                         else
                             case mcl of
-                                Just len -> makeLengthReader len conn
-                                Nothing -> makeUnlimitedReader conn
-                body2 <- if needsGunzip req hs
+                                Just len -> makeLengthReader (cleanup True) len conn
+                                Nothing -> makeUnlimitedReader (cleanup True) conn
+                if needsGunzip req hs
                     then makeGzipReader body1
                     else return body1
-                return $ brAddCleanup (cleanup True) body2
 
     return Response
         { responseStatus = s
diff --git a/http-client.cabal b/http-client.cabal
--- a/http-client.cabal
+++ b/http-client.cabal
@@ -1,5 +1,5 @@
 name:                http-client
-version:             0.6.2
+version:             0.6.3
 synopsis:            An HTTP client engine
 description:         Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/http-client>.
 homepage:            https://github.com/snoyberg/http-client
diff --git a/test-nonet/Network/HTTP/Client/BodySpec.hs b/test-nonet/Network/HTTP/Client/BodySpec.hs
--- a/test-nonet/Network/HTTP/Client/BodySpec.hs
+++ b/test-nonet/Network/HTTP/Client/BodySpec.hs
@@ -22,7 +22,7 @@
         (conn, _, input) <- dummyConnection
             [ "5\r\nhello\r\n6\r\n world\r\n0\r\nnot consumed"
             ]
-        reader <- makeChunkedReader False conn
+        reader <- makeChunkedReader (return ()) False conn
         body <- brConsume reader
         S.concat body `shouldBe` "hello world"
         input' <- input
@@ -32,7 +32,7 @@
     it "chunked, pieces" $ do
         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack
             "5\r\nhello\r\n6\r\n world\r\n0\r\nnot consumed"
-        reader <- makeChunkedReader False conn
+        reader <- makeChunkedReader (return ()) False conn
         body <- brConsume reader
         S.concat body `shouldBe` "hello world"
         input' <- input
@@ -43,7 +43,7 @@
         (conn, _, input) <- dummyConnection
             [ "5\r\nhello\r\n6\r\n world\r\n0\r\nnot consumed"
             ]
-        reader <- makeChunkedReader True conn
+        reader <- makeChunkedReader (return ()) True conn
         body <- brConsume reader
         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\n"
         input' <- input
@@ -53,7 +53,7 @@
     it "chunked, pieces, raw" $ do
         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack
             "5\r\nhello\r\n6\r\n world\r\n0\r\nnot consumed"
-        reader <- makeChunkedReader True conn
+        reader <- makeChunkedReader (return ()) True conn
         body <- brConsume reader
         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\n"
         input' <- input
@@ -64,7 +64,7 @@
         (conn, _, input) <- dummyConnection
             [ "hello world done"
             ]
-        reader <- makeLengthReader 11 conn
+        reader <- makeLengthReader (return ()) 11 conn
         body <- brConsume reader
         S.concat body `shouldBe` "hello world"
         input' <- input
@@ -74,7 +74,7 @@
     it "length, pieces" $ do
         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack
             "hello world done"
-        reader <- makeLengthReader 11 conn
+        reader <- makeLengthReader (return ()) 11 conn
         body <- brConsume reader
         S.concat body `shouldBe` "hello world"
         input' <- input
@@ -85,7 +85,7 @@
         let orig = L.fromChunks $ replicate 5000 "Hello world!"
             origZ = compress orig
         (conn, _, input) <- dummyConnection $ L.toChunks origZ ++ ["ignored"]
-        reader' <- makeLengthReader (fromIntegral $ L.length origZ) conn
+        reader' <- makeLengthReader (return ()) (fromIntegral $ L.length origZ) conn
         reader <- makeGzipReader reader'
         body <- brConsume reader
         L.fromChunks body `shouldBe` orig
