packages feed

http-client 0.7.11 → 0.7.12

raw patch · 6 files changed

+49/−11 lines, 6 filesdep ~base

Dependency ranges changed: base

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for http-client +## 0.7.12++* Fix premature connection closing due to weak reference lifetimes [#490](https://github.com/snoyberg/http-client/pull/490)+ ## 0.7.11  * Allow making requests to raw IPv6 hosts [#477](https://github.com/snoyberg/http-client/pull/477)
Network/HTTP/Client.hs view
@@ -349,9 +349,9 @@ -- >   -- Create the request -- >   let requestObject = object ["name" .= "Michael", "age" .= 30] -- >   let requestObject = object--- >    [ "name" .= ("Michael" :: Text)--- >    , "age"  .= (30 :: Int)--- >    ]+-- >        [ "name" .= ("Michael" :: Text)+-- >        , "age"  .= (30 :: Int)+-- >        ] -- > -- >   initialRequest <- parseRequest "http://httpbin.org/post" -- >   let request = initialRequest { method = "POST", requestBody = RequestBodyLBS $ encode requestObject }
Network/HTTP/Client/Connection.hs view
@@ -210,7 +210,7 @@  -- Pick up an IP using an approximation of the happy-eyeballs algorithm: -- https://datatracker.ietf.org/doc/html/rfc8305--- +-- firstSuccessful :: [NS.AddrInfo] -> (NS.AddrInfo -> IO a) -> IO a firstSuccessful []        _  = error "getAddrInfo returned empty list" firstSuccessful addresses cb = do@@ -226,12 +226,12 @@         z <- forConcurrently (zip addresses [0..]) $ \(addr, n) -> do             when (n > 0) $ threadDelay $ n * connectionAttemptDelay             tryAddress addr-        -        case listToMaybe (reverse z) of -            Just e@(Left _) -> tryPutMVar result e        -            _               -> error $ "tryAddresses invariant violated: " <> show addresses++        case listToMaybe (reverse z) of+            Just e@(Left _) -> tryPutMVar result e+            _               -> error $ "tryAddresses invariant violated: " ++ show addresses       where         tryAddress addr = do             r :: Either E.IOException a <- E.try $! cb addr             for_ r $ \_ -> tryPutMVar result r-            pure r             +            pure r
Network/HTTP/Client/Response.hs view
@@ -97,7 +97,14 @@          -- should we put this connection back into the connection manager?         toPut = Just "close" /= lookup "connection" hs && version > W.HttpVersion 1 0-        cleanup bodyConsumed = managedRelease mconn $ if toPut && bodyConsumed then Reuse else DontReuse+        cleanup bodyConsumed = do+            managedRelease mconn $ if toPut && bodyConsumed then Reuse else DontReuse+            -- Keep alive the `Managed Connection` until we're done with it, to prevent an early+            -- collection.+            -- Reasoning: as long as someone holds a reference to the explicit cleanup,+            -- we shouldn't perform an implicit cleanup.+            keepAlive mconn+      body <-         -- RFC 2616 section 4.4_1 defines responses that must not include a body
http-client.cabal view
@@ -1,5 +1,5 @@ name:                http-client-version:             0.7.11+version:             0.7.12 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
test/Network/HTTP/ClientSpec.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Network.HTTP.ClientSpec where +import           Control.Concurrent (threadDelay) import qualified Data.ByteString.Char8        as BS import           Network.HTTP.Client import           Network.HTTP.Client.Internal@@ -10,6 +11,7 @@ import           Test.Hspec import           Control.Applicative       ((<$>)) import           Data.ByteString.Lazy.Char8 () -- orphan instance+import           System.Mem (performGC)  main :: IO () main = hspec spec@@ -21,6 +23,31 @@         man <- newManager defaultManagerSettings         res <- httpLbs req man         responseStatus res `shouldBe` status200++    -- Test the failure condition described in https://github.com/snoyberg/http-client/issues/489+    it "keeps connection alive long enough" $ do+        req <- parseUrlThrow "http://httpbin.org/"+        man <- newManager defaultManagerSettings+        res <- responseOpen req man+        responseStatus res `shouldBe` status200+        let+            getChunk = responseBody res+            drainAll = do+                chunk <- getChunk+                if BS.null chunk then pure () else drainAll++        -- The returned `BodyReader` used to not contain a reference to the `Managed Connection`,+        -- only to the extracted connection and to the release action. Therefore, triggering a GC+        -- would close the connection even though we were not done reading.+        performGC+        -- Not ideal, but weak finalizers run on a separate thread, so it's racing with our drain+        -- call+        threadDelay 500000++        drainAll+        -- Calling `responseClose res` here prevents the early collection from happening in this+        -- test, but in a larger production application that did involve a `responseClose`, it still+        -- occurred.      describe "method in URL" $ do         it "success" $ do