http-client 0.4.7.2 → 0.4.8
raw patch · 5 files changed
+51/−4 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.HTTP.Client: ResponseLengthAndChunkingBothUsed :: HttpException
+ Network.HTTP.Client.Internal: ResponseLengthAndChunkingBothUsed :: HttpException
Files
- ChangeLog.md +4/−0
- Network/HTTP/Client/Response.hs +8/−2
- Network/HTTP/Client/Types.hs +6/−0
- http-client.cabal +1/−1
- test-nonet/Network/HTTP/ClientSpec.hs +32/−1
ChangeLog.md view
@@ -1,3 +1,7 @@+## 0.4.8++* Add the `ResponseLengthAndChunkingBothUsed` exception constructor [#108](https://github.com/snoyberg/http-client/issues/108)+ ## 0.4.7.2 * Improved `timeout` implementation for high contention cases [#98](https://github.com/snoyberg/http-client/issues/98)
Network/HTTP/Client/Response.hs view
@@ -8,7 +8,7 @@ , lbsResponse ) where -import Control.Monad ((>=>))+import Control.Monad ((>=>), when) import Control.Exception (throwIO) @@ -17,6 +17,8 @@ import Data.Default.Class (def) +import Data.Maybe (isJust)+ import qualified Network.HTTP.Types as W import Network.URI (parseURIReference, escapeURIString, isAllowedInURI) @@ -93,11 +95,16 @@ Just t -> timeout t >=> maybe (throwIO ResponseTimeout) return StatusHeaders s version hs <- timeout' $ parseStatusHeaders conn let mcl = lookup "content-length" hs >>= readDec . S8.unpack+ isChunked = ("transfer-encoding", "chunked") `elem` hs -- should we put this connection back into the connection manager? toPut = Just "close" /= lookup "connection" hs && version > W.HttpVersion 1 0 cleanup bodyConsumed = connRelease $ if toPut && bodyConsumed then Reuse else DontReuse + when (isJust mcl && isChunked) $ do+ cleanup False+ throwIO ResponseLengthAndChunkingBothUsed+ body <- -- RFC 2616 section 4.4_1 defines responses that must not include a body if hasNoBody method (W.statusCode s) || mcl == Just 0@@ -105,7 +112,6 @@ cleanup True return brEmpty else do- let isChunked = ("transfer-encoding", "chunked") `elem` hs body1 <- if isChunked then makeChunkedReader rawBody conn
Network/HTTP/Client/Types.hs view
@@ -114,6 +114,12 @@ -- ^ Environment name and value -- -- Since 0.4.7++ | ResponseLengthAndChunkingBothUsed+ -- ^ Detect a case where both the @content-length@ header+ -- and @transfer-encoding: chunked@ are used.+ --+ -- Since 0.4.8 deriving (Show, T.Typeable) instance Exception HttpException
http-client.cabal view
@@ -1,5 +1,5 @@ name: http-client-version: 0.4.7.2+version: 0.4.8 synopsis: An HTTP client engine, intended as a base layer for more user-friendly packages. 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
test-nonet/Network/HTTP/ClientSpec.hs view
@@ -4,7 +4,7 @@ import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent.Async (withAsync) import Control.Exception (bracket)-import Control.Monad (forever, replicateM_)+import Control.Monad (forever, replicateM_, void) import Network.HTTP.Client import Network.HTTP.Types (status413) import Network.Socket (sClose)@@ -69,6 +69,28 @@ readHeaders S.empty N.appWrite ad "HTTP/1.1 413 Too Large\r\ncontent-length: 7\r\n\r\ngoodbye" +-- Make sure we detect bad situations like+-- https://github.com/yesodweb/wai/issues/346 better than we did previously, so+-- that misreporting like https://github.com/snoyberg/http-client/issues/108+-- doesn't occur.+lengthAndChunked :: (Int -> IO a) -> IO a+lengthAndChunked inner = bracket+ (N.bindRandomPortTCP "*4")+ (sClose . snd)+ $ \(port, lsocket) -> withAsync+ (N.runTCPServer (N.serverSettingsTCPSocket lsocket) app)+ (const $ inner port)+ where+ app ad = do+ let readHeaders front = do+ newBS <- N.appRead ad+ let bs = S.append front newBS+ if "\r\n\r\n" `S.isInfixOf` bs+ then return ()+ else readHeaders bs+ readHeaders S.empty+ N.appWrite ad "HTTP/1.1 200 OK\r\ncontent-length: 0\r\ntransfer-encoding: chunked\r\n\r\n0"+ spec :: Spec spec = describe "Client" $ do describe "fails on empty hostnames #40" $ do@@ -126,3 +148,12 @@ } responseBody res `shouldBe` "goodbye" responseStatus res `shouldBe` status413++ it "length and chunking #108" $ lengthAndChunked $ \port' -> do+ withManager defaultManagerSettings $ \man -> do+ (void $ flip httpLbs man "http://localhost"+ { port = port'+ , checkStatus = \_ _ _ -> Nothing+ , requestBody = RequestBodyStreamChunked+ ($ return (S.replicate 100000 65))+ }) `shouldThrow` (\e -> case e of { ResponseLengthAndChunkingBothUsed -> True; _ -> False})