packages feed

http-client 0.7.13.1 → 0.7.14

raw patch · 13 files changed

+71/−51 lines, 13 filesdep ~deepseqPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: deepseq

API changes (from Hackage documentation)

+ Network.HTTP.Client.Internal: MaxHeaderLength :: Int -> MaxHeaderLength
+ Network.HTTP.Client.Internal: [mMaxHeaderLength] :: Manager -> Maybe MaxHeaderLength
+ Network.HTTP.Client.Internal: [managerMaxHeaderLength] :: ManagerSettings -> Maybe MaxHeaderLength
+ Network.HTTP.Client.Internal: [unMaxHeaderLength] :: MaxHeaderLength -> Int
+ Network.HTTP.Client.Internal: newtype MaxHeaderLength
- Network.HTTP.Client.Internal: Manager :: KeyedPool ConnKey Connection -> ResponseTimeout -> (SomeException -> Bool) -> (forall a. Request -> IO a -> IO a) -> (Request -> IO Request) -> (Request -> Request) -> (Response BodyReader -> IO (Response BodyReader)) -> Manager
+ Network.HTTP.Client.Internal: Manager :: KeyedPool ConnKey Connection -> ResponseTimeout -> (SomeException -> Bool) -> (forall a. Request -> IO a -> IO a) -> (Request -> IO Request) -> (Request -> Request) -> (Response BodyReader -> IO (Response BodyReader)) -> Maybe MaxHeaderLength -> Manager
- Network.HTTP.Client.Internal: ManagerSettings :: Int -> IO (Maybe HostAddress -> String -> Int -> IO Connection) -> IO (Maybe HostAddress -> String -> Int -> IO Connection) -> IO (ByteString -> (Connection -> IO ()) -> String -> Maybe HostAddress -> String -> Int -> IO Connection) -> ResponseTimeout -> (SomeException -> Bool) -> (forall a. Request -> IO a -> IO a) -> Int -> (Request -> IO Request) -> (Response BodyReader -> IO (Response BodyReader)) -> ProxyOverride -> ProxyOverride -> ManagerSettings
+ Network.HTTP.Client.Internal: ManagerSettings :: Int -> IO (Maybe HostAddress -> String -> Int -> IO Connection) -> IO (Maybe HostAddress -> String -> Int -> IO Connection) -> IO (ByteString -> (Connection -> IO ()) -> String -> Maybe HostAddress -> String -> Int -> IO Connection) -> ResponseTimeout -> (SomeException -> Bool) -> (forall a. Request -> IO a -> IO a) -> Int -> (Request -> IO Request) -> (Response BodyReader -> IO (Response BodyReader)) -> ProxyOverride -> ProxyOverride -> Maybe MaxHeaderLength -> ManagerSettings
- Network.HTTP.Client.Internal: connectionDropTillBlankLine :: Connection -> IO ()
+ Network.HTTP.Client.Internal: connectionDropTillBlankLine :: Maybe MaxHeaderLength -> Connection -> IO ()
- Network.HTTP.Client.Internal: connectionReadLine :: Connection -> IO ByteString
+ Network.HTTP.Client.Internal: connectionReadLine :: Maybe MaxHeaderLength -> Connection -> IO ByteString
- Network.HTTP.Client.Internal: connectionReadLineWith :: Connection -> ByteString -> IO ByteString
+ Network.HTTP.Client.Internal: connectionReadLineWith :: Maybe MaxHeaderLength -> Connection -> ByteString -> IO ByteString
- Network.HTTP.Client.Internal: getResponse :: Maybe Int -> Request -> Managed Connection -> Maybe (IO ()) -> IO (Response BodyReader)
+ Network.HTTP.Client.Internal: getResponse :: Maybe MaxHeaderLength -> Maybe Int -> Request -> Managed Connection -> Maybe (IO ()) -> IO (Response BodyReader)
- Network.HTTP.Client.Internal: makeChunkedReader :: IO () -> Bool -> Connection -> IO BodyReader
+ Network.HTTP.Client.Internal: makeChunkedReader :: Maybe MaxHeaderLength -> IO () -> Bool -> Connection -> IO BodyReader
- Network.HTTP.Client.Internal: parseStatusHeaders :: Connection -> Maybe Int -> Maybe (IO ()) -> IO StatusHeaders
+ Network.HTTP.Client.Internal: parseStatusHeaders :: Maybe MaxHeaderLength -> Connection -> Maybe Int -> Maybe (IO ()) -> IO StatusHeaders

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for http-client +## 0.7.14++* Allow customizing max header length [#514](https://github.com/snoyberg/http-client/pull/514)+ ## 0.7.13  * Create the ability to redact custom header values to censor sensitive information
Network/HTTP/Client/Body.hs view
@@ -148,11 +148,12 @@                         return bs  makeChunkedReader-  :: IO () -- ^ cleanup+  :: Maybe MaxHeaderLength+  -> IO () -- ^ cleanup   -> Bool -- ^ raw   -> Connection   -> IO BodyReader-makeChunkedReader cleanup raw conn@Connection {..} = do+makeChunkedReader mhl cleanup raw conn@Connection {..} = do     icount <- newIORef 0     return $ do       bs <- go icount@@ -201,11 +202,11 @@           | otherwise = return (x, 0)      requireNewline = do-        bs <- connectionReadLine conn+        bs <- connectionReadLine mhl conn         unless (S.null bs) $ throwHttp InvalidChunkHeaders      readHeader = do-        bs <- connectionReadLine conn+        bs <- connectionReadLine mhl conn         case parseHex bs of             Nothing -> throwHttp InvalidChunkHeaders             Just hex -> return (bs `S.append` "\r\n", hex)@@ -228,9 +229,9 @@         | otherwise = Nothing      readTrailersRaw = do-        bs <- connectionReadLine conn+        bs <- connectionReadLine mhl conn         if S.null bs         then pure "\r\n"         else (bs `S.append` "\r\n" `S.append`) <$> readTrailersRaw -    consumeTrailers = connectionDropTillBlankLine conn+    consumeTrailers = connectionDropTillBlankLine mhl conn
Network/HTTP/Client/Connection.hs view
@@ -30,28 +30,29 @@ import Data.Maybe (listToMaybe) import Data.Word (Word8) --connectionReadLine :: Connection -> IO ByteString-connectionReadLine conn = do+connectionReadLine :: Maybe MaxHeaderLength -> Connection -> IO ByteString+connectionReadLine mhl conn = do     bs <- connectionRead conn     when (S.null bs) $ throwHttp IncompleteHeaders-    connectionReadLineWith conn bs+    connectionReadLineWith mhl conn bs  -- | Keep dropping input until a blank line is found.-connectionDropTillBlankLine :: Connection -> IO ()-connectionDropTillBlankLine conn = fix $ \loop -> do-    bs <- connectionReadLine conn+connectionDropTillBlankLine :: Maybe MaxHeaderLength -> Connection -> IO ()+connectionDropTillBlankLine mhl conn = fix $ \loop -> do+    bs <- connectionReadLine mhl conn     unless (S.null bs) loop -connectionReadLineWith :: Connection -> ByteString -> IO ByteString-connectionReadLineWith conn bs0 =+connectionReadLineWith :: Maybe MaxHeaderLength -> Connection -> ByteString -> IO ByteString+connectionReadLineWith mhl conn bs0 =     go bs0 id 0   where     go bs front total =         case S.break (== charLF) bs of             (_, "") -> do                 let total' = total + S.length bs-                when (total' > 4096) $ throwHttp OverlongHeaders+                case fmap unMaxHeaderLength mhl of+                    Nothing -> pure ()+                    Just n -> when (total' > n) $ throwHttp OverlongHeaders                 bs' <- connectionRead conn                 when (S.null bs') $ throwHttp IncompleteHeaders                 go bs' (front . (bs:)) total'
Network/HTTP/Client/Core.hs view
@@ -105,7 +105,7 @@     ex <- try $ do         cont <- requestBuilder (dropProxyAuthSecure req) (managedResource mconn) -        getResponse timeout' req mconn cont+        getResponse (mMaxHeaderLength m) timeout' req mconn cont      case ex of         -- Connection was reused, and might have been closed. Try again
Network/HTTP/Client/Headers.hs view
@@ -26,8 +26,8 @@ charPeriod = 46  -parseStatusHeaders :: Connection -> Maybe Int -> Maybe (IO ()) -> IO StatusHeaders-parseStatusHeaders conn timeout' cont+parseStatusHeaders :: Maybe MaxHeaderLength -> Connection -> Maybe Int -> Maybe (IO ()) -> IO StatusHeaders+parseStatusHeaders mhl conn timeout' cont     | Just k <- cont = getStatusExpectContinue k     | otherwise      = getStatus   where@@ -46,22 +46,22 @@             Nothing -> sendBody >> getStatus      nextStatusHeaders = do-        (s, v) <- nextStatusLine+        (s, v) <- nextStatusLine mhl         if statusCode s == 100-            then connectionDropTillBlankLine conn >> return Nothing+            then connectionDropTillBlankLine mhl conn >> return Nothing             else Just . StatusHeaders s v A.<$> parseHeaders (0 :: Int) id -    nextStatusLine :: IO (Status, HttpVersion)-    nextStatusLine = do+    nextStatusLine :: Maybe MaxHeaderLength -> IO (Status, HttpVersion)+    nextStatusLine mhl = do         -- Ensure that there is some data coming in. If not, we want to signal         -- this as a connection problem and not a protocol problem.         bs <- connectionRead conn         when (S.null bs) $ throwHttp NoResponseDataReceived-        connectionReadLineWith conn bs >>= parseStatus 3+        connectionReadLineWith mhl conn bs >>= parseStatus mhl 3 -    parseStatus :: Int -> S.ByteString -> IO (Status, HttpVersion)-    parseStatus i bs | S.null bs && i > 0 = connectionReadLine conn >>= parseStatus (i - 1)-    parseStatus _ bs = do+    parseStatus :: Maybe MaxHeaderLength -> Int -> S.ByteString -> IO (Status, HttpVersion)+    parseStatus mhl i bs | S.null bs && i > 0 = connectionReadLine mhl conn >>= parseStatus mhl (i - 1)+    parseStatus _ _ bs = do         let (ver, bs2) = S.break (== charSpace) bs             (code, bs3) = S.break (== charSpace) $ S.dropWhile (== charSpace) bs2             msg = S.dropWhile (== charSpace) bs3@@ -84,7 +84,7 @@      parseHeaders 100 _ = throwHttp OverlongHeaders     parseHeaders count front = do-        line <- connectionReadLine conn+        line <- connectionReadLine mhl conn         if S.null line             then return $ front []             else do
Network/HTTP/Client/Manager.hs view
@@ -92,6 +92,7 @@     , managerModifyResponse = return     , managerProxyInsecure = defaultProxy     , managerProxySecure = defaultProxy+    , managerMaxHeaderLength = Just $ MaxHeaderLength 4096     }  -- | Create a 'Manager'. The @Manager@ will be shut down automatically via@@ -131,6 +132,7 @@                 if secure req                     then httpsProxy req                     else httpProxy req+            , mMaxHeaderLength = managerMaxHeaderLength ms             }     return manager @@ -257,7 +259,7 @@                     , "\r\n"                     ]                 parse conn = do-                    StatusHeaders status _ _ <- parseStatusHeaders conn Nothing Nothing+                    StatusHeaders status _ _ <- parseStatusHeaders (managerMaxHeaderLength ms) conn Nothing Nothing                     unless (status == status200) $                         throwHttp $ ProxyConnectException ultHost ultPort status                 in tlsProxyConnection
Network/HTTP/Client/Request.hs view
@@ -122,9 +122,9 @@ -- You can place the request method at the beginning of the URL separated by a -- space, e.g.: ----- @@@+-- @ -- parseRequest "POST http://httpbin.org/post"--- @@@+-- @ -- -- Note that the request method must be provided as all capital letters. --
Network/HTTP/Client/Response.hs view
@@ -84,14 +84,15 @@         { responseBody = L.fromChunks bss         } -getResponse :: Maybe Int+getResponse :: Maybe MaxHeaderLength+            -> Maybe Int             -> Request             -> Managed Connection             -> Maybe (IO ()) -- ^ Action to run in case of a '100 Continue'.             -> IO (Response BodyReader)-getResponse timeout' req@(Request {..}) mconn cont = do+getResponse mhl timeout' req@(Request {..}) mconn cont = do     let conn = managedResource mconn-    StatusHeaders s version hs <- parseStatusHeaders conn timeout' cont+    StatusHeaders s version hs <- parseStatusHeaders mhl conn timeout' cont     let mcl = lookup "content-length" hs >>= readPositiveInt . S8.unpack         isChunked = ("transfer-encoding", CI.mk "chunked") `elem` map (second CI.mk) hs @@ -115,7 +116,7 @@             else do                 body1 <-                     if isChunked-                        then makeChunkedReader (cleanup True) rawBody conn+                        then makeChunkedReader mhl (cleanup True) rawBody conn                         else                             case mcl of                                 Just len -> makeLengthReader (cleanup True) len conn
Network/HTTP/Client/Types.hs view
@@ -38,6 +38,7 @@     , StreamFileStatus (..)     , ResponseTimeout (..)     , ProxySecureMode (..)+    , MaxHeaderLength (..)     ) where  import qualified Data.Typeable as T (Typeable)@@ -703,7 +704,7 @@     -- Since 0.1.0     , responseOriginalRequest :: Request     -- ^ Holds original @Request@ related to this @Response@ (with an empty body).-    -- This field is intentionally not exported directly, but made availble+    -- This field is intentionally not exported directly, but made available     -- via @getOriginalRequest@ instead.     --     -- Since 0.7.8@@ -802,6 +803,7 @@     -- Default: respect the @proxy@ value on the @Request@ itself.     --     -- Since 0.4.7+    , managerMaxHeaderLength :: Maybe MaxHeaderLength     }     deriving T.Typeable @@ -828,6 +830,7 @@     , mSetProxy :: Request -> Request     , mModifyResponse      :: Response BodyReader -> IO (Response BodyReader)     -- ^ See 'managerProxy'+    , mMaxHeaderLength :: Maybe MaxHeaderLength     }     deriving T.Typeable @@ -879,3 +882,11 @@     , thisChunkSize :: Int     }     deriving (Eq, Show, Ord, T.Typeable)++-- | The maximum header size in bytes.+--+-- @since 0.7.14+newtype MaxHeaderLength = MaxHeaderLength+    { unMaxHeaderLength :: Int+    }+    deriving (Eq, Show)
http-client.cabal view
@@ -1,5 +1,5 @@ name:                http-client-version:             0.7.13.1+version:             0.7.14 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@@ -59,7 +59,7 @@                      , ghc-prim                      , stm               >= 2.3                      , iproute           >= 1.7.5-                     , async+                     , async             >= 2.0   if flag(network-uri)     build-depends: network >= 2.6, network-uri >= 2.6   else
test-nonet/Network/HTTP/Client/BodySpec.hs view
@@ -22,7 +22,7 @@         (conn, _, input) <- dummyConnection             [ "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\nnot consumed"             ]-        reader <- makeChunkedReader (return ()) False conn+        reader <- makeChunkedReader Nothing (return ()) False conn         body <- brConsume reader         S.concat body `shouldBe` "hello world"         input' <- input@@ -33,7 +33,7 @@         (conn, _, input) <- dummyConnection             [ "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: ignored\r\nbut: consumed\r\n\r\nnot consumed"             ]-        reader <- makeChunkedReader (return ()) False conn+        reader <- makeChunkedReader Nothing (return ()) False conn         body <- brConsume reader         S.concat body `shouldBe` "hello world"         input' <- input@@ -43,7 +43,7 @@     it "chunked, pieces" $ do         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack             "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\nnot consumed"-        reader <- makeChunkedReader (return ()) False conn+        reader <- makeChunkedReader Nothing (return ()) False conn         body <- brConsume reader         S.concat body `shouldBe` "hello world"         input' <- input@@ -53,7 +53,7 @@     it "chunked, pieces, with trailers" $ do         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack             "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: ignored\r\nbut: consumed\r\n\r\nnot consumed"-        reader <- makeChunkedReader (return ()) False conn+        reader <- makeChunkedReader Nothing (return ()) False conn         body <- brConsume reader         S.concat body `shouldBe` "hello world"         input' <- input@@ -64,7 +64,7 @@         (conn, _, input) <- dummyConnection             [ "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\nnot consumed"             ]-        reader <- makeChunkedReader (return ()) True conn+        reader <- makeChunkedReader Nothing (return ()) True conn         body <- brConsume reader         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\n"         input' <- input@@ -75,7 +75,7 @@         (conn, _, input) <- dummyConnection             [ "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: returned\r\nin-raw: body\r\n\r\nnot consumed"             ]-        reader <- makeChunkedReader (return ()) True conn+        reader <- makeChunkedReader Nothing (return ()) True conn         body <- brConsume reader         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: returned\r\nin-raw: body\r\n\r\n"         input' <- input@@ -85,7 +85,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\n\r\nnot consumed"-        reader <- makeChunkedReader (return ()) True conn+        reader <- makeChunkedReader Nothing (return ()) True conn         body <- brConsume reader         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\n"         input' <- input@@ -95,7 +95,7 @@     it "chunked, pieces, raw, with trailers" $ do         (conn, _, input) <- dummyConnection $ map S.singleton $ S.unpack             "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: returned\r\nin-raw: body\r\n\r\nnot consumed"-        reader <- makeChunkedReader (return ()) True conn+        reader <- makeChunkedReader Nothing (return ()) True conn         body <- brConsume reader         S.concat body `shouldBe` "5\r\nhello\r\n6\r\n world\r\n0\r\ntrailers-are: returned\r\nin-raw: body\r\n\r\n"         input' <- input
test-nonet/Network/HTTP/Client/HeadersSpec.hs view
@@ -20,7 +20,7 @@                 , "\nignored"                 ]         (connection, _, _) <- dummyConnection input-        statusHeaders <- parseStatusHeaders connection Nothing Nothing+        statusHeaders <- parseStatusHeaders Nothing connection Nothing Nothing         statusHeaders `shouldBe` StatusHeaders status200 (HttpVersion 1 1)             [ ("foo", "bar")             , ("baz", "bin")@@ -34,7 +34,7 @@                 ]         (conn, out, _) <- dummyConnection input         let sendBody = connectionWrite conn "data"-        statusHeaders <- parseStatusHeaders conn Nothing (Just sendBody)+        statusHeaders <- parseStatusHeaders Nothing conn Nothing (Just sendBody)         statusHeaders `shouldBe` StatusHeaders status200 (HttpVersion 1 1) [ ("foo", "bar") ]         out >>= (`shouldBe` ["data"]) @@ -44,7 +44,7 @@                 ]         (conn, out, _) <- dummyConnection input         let sendBody = connectionWrite conn "data"-        statusHeaders <- parseStatusHeaders conn Nothing (Just sendBody)+        statusHeaders <- parseStatusHeaders Nothing conn Nothing (Just sendBody)         statusHeaders `shouldBe` StatusHeaders status417 (HttpVersion 1 1) []         out >>= (`shouldBe` []) @@ -56,7 +56,7 @@                 , "result"                 ]         (conn, out, inp) <- dummyConnection input-        statusHeaders <- parseStatusHeaders conn Nothing Nothing+        statusHeaders <- parseStatusHeaders Nothing conn Nothing Nothing         statusHeaders `shouldBe` StatusHeaders status200 (HttpVersion 1 1) [ ("foo", "bar") ]         out >>= (`shouldBe` [])         inp >>= (`shouldBe` ["result"])
test-nonet/Network/HTTP/Client/ResponseSpec.hs view
@@ -16,7 +16,7 @@  spec :: Spec spec = describe "ResponseSpec" $ do-    let getResponse' conn = getResponse Nothing req (dummyManaged conn) Nothing+    let getResponse' conn = getResponse Nothing Nothing req (dummyManaged conn) Nothing         req = parseRequest_ "http://localhost"     it "basic" $ do         (conn, _, _) <- dummyConnection