diff -Nru haskell-http-client-0.7.11/ChangeLog.md haskell-http-client-0.7.13.1/ChangeLog.md --- haskell-http-client-0.7.11/ChangeLog.md 2022-02-04 09:27:01.000000000 +0000 +++ haskell-http-client-0.7.13.1/ChangeLog.md 2022-08-02 13:59:11.000000000 +0000 @@ -1,5 +1,13 @@ # Changelog for http-client +## 0.7.13 + +* Create the ability to redact custom header values to censor sensitive information + +## 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) diff -Nru haskell-http-client-0.7.11/debian/changelog haskell-http-client-0.7.13.1/debian/changelog --- haskell-http-client-0.7.11/debian/changelog 2022-07-24 11:41:26.000000000 +0000 +++ haskell-http-client-0.7.13.1/debian/changelog 2022-12-12 02:49:19.000000000 +0000 @@ -1,3 +1,15 @@ +haskell-http-client (0.7.13.1-1build1) lunar; urgency=medium + + * Rebuild against new GHC ABI. + + -- Gianfranco Costamagna Mon, 12 Dec 2022 03:49:19 +0100 + +haskell-http-client (0.7.13.1-1) unstable; urgency=medium + + * New upstream release + + -- Ilias Tsitsimpis Sun, 23 Oct 2022 18:20:07 +0300 + haskell-http-client (0.7.11-1) unstable; urgency=medium * New upstream release (Closes: #856700) diff -Nru haskell-http-client-0.7.11/debian/patches/disable-external-network-connection-test.diff haskell-http-client-0.7.13.1/debian/patches/disable-external-network-connection-test.diff --- haskell-http-client-0.7.11/debian/patches/disable-external-network-connection-test.diff 2022-07-24 11:41:26.000000000 +0000 +++ haskell-http-client-0.7.13.1/debian/patches/disable-external-network-connection-test.diff 2022-10-23 15:20:07.000000000 +0000 @@ -2,7 +2,7 @@ =================================================================== --- a/test/Network/HTTP/ClientSpec.hs +++ b/test/Network/HTTP/ClientSpec.hs -@@ -15,115 +15,4 @@ main :: IO () +@@ -17,140 +17,4 @@ main :: IO () main = hspec spec spec :: Spec @@ -13,6 +13,31 @@ - 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 - req <- parseUrlThrow "POST http://httpbin.org/post" diff -Nru haskell-http-client-0.7.11/http-client.cabal haskell-http-client-0.7.13.1/http-client.cabal --- haskell-http-client-0.7.11/http-client.cabal 2022-02-04 09:26:32.000000000 +0000 +++ haskell-http-client-0.7.13.1/http-client.cabal 2022-08-04 11:11:05.000000000 +0000 @@ -1,5 +1,5 @@ name: http-client -version: 0.7.11 +version: 0.7.13.1 synopsis: An HTTP client engine description: Hackage documentation generation is not reliable. For up to date documentation, please see: . homepage: https://github.com/snoyberg/http-client diff -Nru haskell-http-client-0.7.11/Network/HTTP/Client/Connection.hs haskell-http-client-0.7.13.1/Network/HTTP/Client/Connection.hs --- haskell-http-client-0.7.11/Network/HTTP/Client/Connection.hs 2022-02-04 09:26:32.000000000 +0000 +++ haskell-http-client-0.7.13.1/Network/HTTP/Client/Connection.hs 2022-02-11 02:59:48.000000000 +0000 @@ -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 \ No newline at end of file + pure r diff -Nru haskell-http-client-0.7.11/Network/HTTP/Client/Request.hs haskell-http-client-0.7.13.1/Network/HTTP/Client/Request.hs --- haskell-http-client-0.7.11/Network/HTTP/Client/Request.hs 2022-01-31 15:09:24.000000000 +0000 +++ haskell-http-client-0.7.13.1/Network/HTTP/Client/Request.hs 2022-08-02 13:59:11.000000000 +0000 @@ -49,6 +49,7 @@ import Control.Monad (unless, guard) import Control.Monad.IO.Class (MonadIO, liftIO) import Numeric (showHex) +import qualified Data.Set as Set import Blaze.ByteString.Builder (Builder, fromByteString, fromLazyByteString, toByteStringIO, flush) import Blaze.ByteString.Builder.Char8 (fromChar, fromShow) @@ -303,6 +304,7 @@ , requestManagerOverride = Nothing , shouldStripHeaderOnRedirect = const False , proxySecureMode = ProxySecureWithConnect + , redactHeaders = Set.singleton "Authorization" } -- | Parses a URL via 'parseRequest_' diff -Nru haskell-http-client-0.7.11/Network/HTTP/Client/Response.hs haskell-http-client-0.7.13.1/Network/HTTP/Client/Response.hs --- haskell-http-client-0.7.11/Network/HTTP/Client/Response.hs 2022-01-31 15:09:24.000000000 +0000 +++ haskell-http-client-0.7.13.1/Network/HTTP/Client/Response.hs 2022-07-26 01:36:13.000000000 +0000 @@ -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 diff -Nru haskell-http-client-0.7.11/Network/HTTP/Client/Types.hs haskell-http-client-0.7.13.1/Network/HTTP/Client/Types.hs --- haskell-http-client-0.7.11/Network/HTTP/Client/Types.hs 2022-01-31 15:09:24.000000000 +0000 +++ haskell-http-client-0.7.13.1/Network/HTTP/Client/Types.hs 2022-08-02 13:59:11.000000000 +0000 @@ -59,6 +59,7 @@ import Data.IORef import qualified Network.Socket as NS import qualified Data.Map as Map +import qualified Data.Set as Set import Data.Text (Text) import Data.Streaming.Zlib (ZlibException) import Data.CaseInsensitive as CI @@ -620,6 +621,11 @@ -- Default: Use HTTP CONNECT. -- -- @since 0.7.2 + + , redactHeaders :: Set.Set HeaderName + -- ^ List of header values being redacted in case we show Request. + -- + -- @since 0.7.13 } deriving T.Typeable @@ -643,7 +649,7 @@ , " host = " ++ show (host x) , " port = " ++ show (port x) , " secure = " ++ show (secure x) - , " requestHeaders = " ++ show (DL.map redactSensitiveHeader (requestHeaders x)) + , " requestHeaders = " ++ show (DL.map (redactSensitiveHeader $ redactHeaders x) (requestHeaders x)) , " path = " ++ show (path x) , " queryString = " ++ show (queryString x) --, " requestBody = " ++ show (requestBody x) @@ -657,9 +663,11 @@ , "}" ] -redactSensitiveHeader :: Header -> Header -redactSensitiveHeader ("Authorization", _) = ("Authorization", "") -redactSensitiveHeader h = h +redactSensitiveHeader :: Set.Set HeaderName -> Header -> Header +redactSensitiveHeader toRedact h@(name, _) = + if name `Set.member` toRedact + then (name, "") + else h -- | A simple representation of the HTTP response. -- diff -Nru haskell-http-client-0.7.11/Network/HTTP/Client.hs haskell-http-client-0.7.13.1/Network/HTTP/Client.hs --- haskell-http-client-0.7.11/Network/HTTP/Client.hs 2022-01-31 15:09:24.000000000 +0000 +++ haskell-http-client-0.7.13.1/Network/HTTP/Client.hs 2022-08-04 11:11:05.000000000 +0000 @@ -166,6 +166,7 @@ , responseTimeout , cookieJar , requestVersion + , redactHeaders -- ** Request body , RequestBody (..) , Popper @@ -349,9 +350,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 } diff -Nru haskell-http-client-0.7.11/test/Network/HTTP/ClientSpec.hs haskell-http-client-0.7.13.1/test/Network/HTTP/ClientSpec.hs --- haskell-http-client-0.7.11/test/Network/HTTP/ClientSpec.hs 2022-01-31 15:09:24.000000000 +0000 +++ haskell-http-client-0.7.13.1/test/Network/HTTP/ClientSpec.hs 2022-07-26 01:36:13.000000000 +0000 @@ -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 @@ -22,6 +24,31 @@ 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 req <- parseUrlThrow "POST http://httpbin.org/post"