http-kit 0.4.0 → 0.5.0
raw patch · 8 files changed
+175/−105 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Network.HTTP.Toolkit: data Connection
- Network.HTTP.Toolkit.Connection: Connection :: IO ByteString -> (ByteString -> IO ()) -> Connection
- Network.HTTP.Toolkit.Connection: data Connection
+ Network.HTTP.Toolkit: data InputStream
+ Network.HTTP.Toolkit: inputStreamFromHandle :: Handle -> IO InputStream
+ Network.HTTP.Toolkit: makeInputStream :: IO ByteString -> IO InputStream
+ Network.HTTP.Toolkit: type Connection = InputStream
+ Network.HTTP.Toolkit.Connection: InputStream :: IO ByteString -> (ByteString -> IO ()) -> InputStream
+ Network.HTTP.Toolkit.Connection: data InputStream
+ Network.HTTP.Toolkit.Connection: type Connection = InputStream
+ Network.HTTP.Toolkit.InputStream: InputStream :: IO ByteString -> (ByteString -> IO ()) -> InputStream
+ Network.HTTP.Toolkit.InputStream: _read :: InputStream -> IO ByteString
+ Network.HTTP.Toolkit.InputStream: _unread :: InputStream -> ByteString -> IO ()
+ Network.HTTP.Toolkit.InputStream: data InputStream
+ Network.HTTP.Toolkit.InputStream: inputStreamFromHandle :: Handle -> IO InputStream
+ Network.HTTP.Toolkit.InputStream: makeInputStream :: IO ByteString -> IO InputStream
+ Network.HTTP.Toolkit.InputStream: readAtLeast :: InputStream -> Int -> IO ByteString
+ Network.HTTP.Toolkit.InputStream: readInput :: InputStream -> IO ByteString
+ Network.HTTP.Toolkit.InputStream: unreadInput :: InputStream -> ByteString -> IO ()
+ Network.HTTP.Toolkit.Request: instance Foldable Request
+ Network.HTTP.Toolkit.Request: instance Traversable Request
+ Network.HTTP.Toolkit.Response: instance Foldable Response
+ Network.HTTP.Toolkit.Response: instance Traversable Response
- Network.HTTP.Toolkit: readRequest :: Connection -> IO (Request BodyReader)
+ Network.HTTP.Toolkit: readRequest :: Bool -> InputStream -> IO (Request BodyReader)
- Network.HTTP.Toolkit: readRequestWithLimit :: Limit -> Connection -> IO (Request BodyReader)
+ Network.HTTP.Toolkit: readRequestWithLimit :: Limit -> Bool -> InputStream -> IO (Request BodyReader)
- Network.HTTP.Toolkit: readResponse :: Method -> Connection -> IO (Response BodyReader)
+ Network.HTTP.Toolkit: readResponse :: Bool -> Method -> InputStream -> IO (Response BodyReader)
- Network.HTTP.Toolkit: readResponseWithLimit :: Limit -> Method -> Connection -> IO (Response BodyReader)
+ Network.HTTP.Toolkit: readResponseWithLimit :: Limit -> Bool -> Method -> InputStream -> IO (Response BodyReader)
- Network.HTTP.Toolkit.Body: makeBodyReader :: Connection -> BodyType -> IO BodyReader
+ Network.HTTP.Toolkit.Body: makeBodyReader :: Bool -> BodyType -> InputStream -> IO BodyReader
- Network.HTTP.Toolkit.Body: makeChunkedReader :: Connection -> IO BodyReader
+ Network.HTTP.Toolkit.Body: makeChunkedReader :: Bool -> InputStream -> IO BodyReader
- Network.HTTP.Toolkit.Body: makeLengthReader :: Int -> Connection -> IO BodyReader
+ Network.HTTP.Toolkit.Body: makeLengthReader :: Int -> InputStream -> IO BodyReader
- Network.HTTP.Toolkit.Body: makeUnlimitedReader :: Connection -> IO BodyReader
+ Network.HTTP.Toolkit.Body: makeUnlimitedReader :: InputStream -> IO BodyReader
- Network.HTTP.Toolkit.Body: readChunkSize :: Connection -> IO (Int, ByteString)
+ Network.HTTP.Toolkit.Body: readChunkSize :: InputStream -> IO (Int, ByteString)
- Network.HTTP.Toolkit.Connection: _read :: Connection -> IO ByteString
+ Network.HTTP.Toolkit.Connection: _read :: InputStream -> IO ByteString
- Network.HTTP.Toolkit.Connection: _unread :: Connection -> ByteString -> IO ()
+ Network.HTTP.Toolkit.Connection: _unread :: InputStream -> ByteString -> IO ()
- Network.HTTP.Toolkit.Header: readHeaderLines :: Limit -> Connection -> IO [ByteString]
+ Network.HTTP.Toolkit.Header: readHeaderLines :: Limit -> InputStream -> IO [ByteString]
- Network.HTTP.Toolkit.Header: readMessageHeader :: Limit -> Connection -> IO (ByteString, [Header])
+ Network.HTTP.Toolkit.Header: readMessageHeader :: Limit -> InputStream -> IO (ByteString, [Header])
- Network.HTTP.Toolkit.Request: readRequest :: Connection -> IO (Request BodyReader)
+ Network.HTTP.Toolkit.Request: readRequest :: Bool -> InputStream -> IO (Request BodyReader)
- Network.HTTP.Toolkit.Request: readRequestWithLimit :: Limit -> Connection -> IO (Request BodyReader)
+ Network.HTTP.Toolkit.Request: readRequestWithLimit :: Limit -> Bool -> InputStream -> IO (Request BodyReader)
- Network.HTTP.Toolkit.Response: readResponse :: Method -> Connection -> IO (Response BodyReader)
+ Network.HTTP.Toolkit.Response: readResponse :: Bool -> Method -> InputStream -> IO (Response BodyReader)
- Network.HTTP.Toolkit.Response: readResponseWithLimit :: Limit -> Method -> Connection -> IO (Response BodyReader)
+ Network.HTTP.Toolkit.Response: readResponseWithLimit :: Limit -> Bool -> Method -> InputStream -> IO (Response BodyReader)
Files
- http-kit.cabal +5/−2
- src/Network/HTTP/Toolkit.hs +12/−4
- src/Network/HTTP/Toolkit/Body.hs +52/−32
- src/Network/HTTP/Toolkit/Connection.hs +13/−44
- src/Network/HTTP/Toolkit/Header.hs +7/−7
- src/Network/HTTP/Toolkit/InputStream.hs +62/−0
- src/Network/HTTP/Toolkit/Request.hs +12/−8
- src/Network/HTTP/Toolkit/Response.hs +12/−8
http-kit.cabal view
@@ -1,5 +1,5 @@ name: http-kit-version: 0.4.0+version: 0.5.0 synopsis: A low-level HTTP library description: A low-level HTTP library that can be used to build more sophisticated applications on top of it.@@ -22,7 +22,7 @@ maintainer: Simon Hengel <sol@typeful.net> build-type: Simple category: Network-cabal-version: >= 1.8+cabal-version: >= 1.10 source-repository head type: git@@ -37,6 +37,7 @@ Network.HTTP.Toolkit Network.HTTP.Toolkit.Body Network.HTTP.Toolkit.Connection+ Network.HTTP.Toolkit.InputStream Network.HTTP.Toolkit.Header Network.HTTP.Toolkit.Request Network.HTTP.Toolkit.Response@@ -48,6 +49,7 @@ , bytestring , http-types , case-insensitive+ default-language: Haskell2010 test-suite spec type:@@ -66,3 +68,4 @@ , hspec >= 1.9 , QuickCheck , quickcheck-instances+ default-language: Haskell2010
src/Network/HTTP/Toolkit.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-} module Network.HTTP.Toolkit ( -- * Exceptions -- |@@ -8,11 +9,12 @@ -- @UnexpectedEndOfInput@ are documented thoroughly on a per function level. -- ToolkitError(..)--- * Connection-, Connection-, makeConnection-, connectionFromHandle +-- * Input handling+, InputStream+, makeInputStream+, inputStreamFromHandle+ -- * Handling requests , RequestPath , Request(..)@@ -31,9 +33,15 @@ , BodyReader , sendBody , consumeBody++-- * Deprecated types and functions+, Connection+, makeConnection+, connectionFromHandle ) where import Network.HTTP.Toolkit.Body+import Network.HTTP.Toolkit.InputStream import Network.HTTP.Toolkit.Connection import Network.HTTP.Toolkit.Request import Network.HTTP.Toolkit.Response
src/Network/HTTP/Toolkit/Body.hs view
@@ -32,7 +32,7 @@ import Network.HTTP.Toolkit.Util import Network.HTTP.Toolkit.Error-import Network.HTTP.Toolkit.Connection+import Network.HTTP.Toolkit.InputStream data BodyType = -- | The message has no body.@@ -62,10 +62,12 @@ chunked = lookup "Transfer-Encoding" headers >>= guard . (/= "identity") >> Just Chunked length_ = Length <$> (lookup "Content-Length" headers >>= readMaybe . B8.unpack) --- | Create a `BodyReader` from provided `Connection` and specified `BodyType`.-makeBodyReader :: Connection -> BodyType -> IO BodyReader-makeBodyReader c bodyType = case bodyType of- Chunked -> makeChunkedReader c+-- | Create a `BodyReader` from provided `InputStream` and specified `BodyType`.+--+-- The first argument is passed to `makeChunkedReader`.+makeBodyReader :: Bool -> BodyType -> InputStream -> IO BodyReader+makeBodyReader raw bodyType c = case bodyType of+ Chunked -> makeChunkedReader raw c Length n -> makeLengthReader n c Unlimited -> makeUnlimitedReader c None -> return (pure "")@@ -116,7 +118,7 @@ -- | -- Create a reader for when the body length is determined by the server closing -- the connection.-makeUnlimitedReader :: Connection -> IO BodyReader+makeUnlimitedReader :: InputStream -> IO BodyReader makeUnlimitedReader c = do ref <- newIORef False return $ do@@ -124,13 +126,13 @@ if done then return "" else do- xs <- connectionRead c `catchOnly` UnexpectedEndOfInput $ do+ xs <- readInput c `catchOnly` UnexpectedEndOfInput $ do writeIORef ref True return "" return xs -- | Create a reader for bodies with a specified length.-makeLengthReader :: Int -> Connection -> IO BodyReader+makeLengthReader :: Int -> InputStream -> IO BodyReader makeLengthReader total c = do ref <- newIORef total return $ do@@ -138,27 +140,33 @@ if n == 0 then return "" else do- bs <- connectionRead c+ bs <- readInput c case B.splitAt n bs of (xs, ys) -> do writeIORef ref (n - B.length xs)- connectionUnread c ys+ unreadInput c ys return xs data Where = Data | Extension -data State = More Int Where | Trailer | Done+data State = Begin | More Int Where | Trailer | Done -- | Create a reader for bodies with chunked transfer coding. --+-- If the first argument is `True` the body is returned raw, including chunk+-- sizes, chunk extensions and trailer.+--+-- If the first argument is `False` only the decoded body is returned, chunk+-- extensions and trailer are striped.+-- -- The reader throws: -- -- * `InvalidChunk` if the body is malformed. -- -- * `ChunkTooLarge` if the size of a chunk exceeds `maxChunkSize`.-makeChunkedReader :: Connection -> IO BodyReader-makeChunkedReader conn = do- ref <- newIORef (More 0 Data)+makeChunkedReader :: Bool -> InputStream -> IO BodyReader+makeChunkedReader raw conn = do+ ref <- newIORef Begin return $ go ref `catchOnly` UnexpectedEndOfInput $ do writeIORef ref Done return ""@@ -166,51 +174,63 @@ go ref = do c <- readIORef ref case c of- More 0 Data -> do+ Begin -> do (n, xs) <- readChunkSize conn writeIORef ref (More n Extension)- return xs+ if raw then return xs else go ref More n Extension -> do- bs <- connectionRead conn+ bs <- readInput conn case breakOnNewline bs of ("", _) -> if n > 0 then do- handleChunkData ref (n + 3) bs+ if raw then do+ unreadInput conn bs+ handleChunkData ref (n + 1)+ else do+ unreadInput conn (B.tail bs)+ handleChunkData ref n else do writeIORef ref Trailer- connectionUnread conn bs+ unreadInput conn bs readTrailer ref (xs, ys) -> do- connectionUnread conn ys- return xs+ unreadInput conn ys+ if raw then return xs else go ref+ More 0 Data -> do+ bs <- readAtLeast conn 2+ let (xs, ys) = B.splitAt 2 bs+ unreadInput conn ys+ writeIORef ref Begin+ if raw then return xs else go ref More n Data -> do- connectionRead conn >>= handleChunkData ref n+ handleChunkData ref n Trailer -> readTrailer ref Done -> return "" - handleChunkData :: IORef State -> Int -> ByteString -> IO ByteString- handleChunkData ref n bs = do+ handleChunkData :: IORef State -> Int -> IO ByteString+ handleChunkData ref n = do+ bs <- readInput conn let (xs, ys) = B.splitAt n bs- connectionUnread conn ys+ unreadInput conn ys writeIORef ref (More (n - B.length xs) Data) return xs readTrailer :: IORef State -> IO ByteString readTrailer ref = do- xs <- connectionReadAtLeast conn 3+ xs <- readAtLeast conn 3 if "\n\r\n" `B.isPrefixOf` xs then do writeIORef ref Done let (ys, zs) = B.splitAt 3 xs- connectionUnread conn zs- return ys+ unreadInput conn zs+ if raw then return ys else return "" else do let Just (y, ys) = B.uncons xs case breakOnNewline ys of (zs, rest) -> do- connectionUnread conn rest- return (y `B.cons` zs)+ unreadInput conn rest+ if raw then return (y `B.cons` zs) else go ref breakOnNewline :: ByteString -> (ByteString, ByteString) breakOnNewline = breakByte 10@@ -221,7 +241,7 @@ -- Throws: -- -- * `ChunkTooLarge` if chunk size exceeds `maxChunkSize`.-readChunkSize :: Connection -> IO (Int, ByteString)+readChunkSize :: InputStream -> IO (Int, ByteString) readChunkSize conn = do xs <- go 0 case readHex (B8.unpack xs) of@@ -230,7 +250,7 @@ where go :: Int -> IO ByteString go n = do- bs <- connectionRead conn+ bs <- readInput conn case B8.span isHexDigit bs of (xs, ys) -> do let m = (n + B.length xs)
src/Network/HTTP/Toolkit/Connection.hs view
@@ -1,5 +1,6 @@-module Network.HTTP.Toolkit.Connection (- Connection(..)+module Network.HTTP.Toolkit.Connection {-# DEPRECATED "use \"Network.HTTP.Toolkit.InputStream\" instead" #-} (+ Connection+, InputStream(..) , makeConnection , connectionFromHandle , connectionRead@@ -7,56 +8,24 @@ , connectionReadAtLeast ) where -import Prelude hiding (read)-import Control.Monad (join, when, unless)-import Control.Exception-import System.IO (Handle)-import Data.IORef+import System.IO import Data.ByteString (ByteString)-import qualified Data.ByteString as B -import Network.HTTP.Toolkit.Error---- | An abstract connection type that allows to read and unread input.-data Connection = Connection {- _read :: IO ByteString-, _unread :: ByteString -> IO ()-}+import Network.HTTP.Toolkit.InputStream --- | Create a `Connection` from provided `Handle`.-connectionFromHandle :: Handle -> IO Connection-connectionFromHandle h = makeConnection (B.hGetSome h 4096)+type Connection = InputStream --- | Create a `Connection` from provided @IO@ action. makeConnection :: IO ByteString -> IO Connection-makeConnection read = do- ref <- newIORef []- return $ Connection {- _read = join $ atomicModifyIORef ref $ \xs -> case xs of- y : ys -> (ys, return y)- _ -> (xs, read)- , _unread = \x -> atomicModifyIORef ref $ \xs -> (x : xs, ())- }+makeConnection = makeInputStream --- | Read some input.+connectionFromHandle :: Handle -> IO Connection+connectionFromHandle = inputStreamFromHandle+ connectionRead :: Connection -> IO ByteString-connectionRead c = do- bs <- _read c- when (B.null bs) $ throwIO UnexpectedEndOfInput- return bs+connectionRead = readInput --- | Push back some input. The pushed back input will be returned by a later--- call to `connectionRead`. connectionUnread :: Connection -> ByteString -> IO ()-connectionUnread conn bs = unless (B.null bs) (_unread conn bs)+connectionUnread = unreadInput --- | Read at least the specified number of bytes from the input stream. connectionReadAtLeast :: Connection -> Int -> IO ByteString-connectionReadAtLeast conn n = connectionRead conn >>= go- where- go :: ByteString -> IO ByteString- go xs- | B.length xs < n = do- ys <- connectionRead conn- go (xs `B.append` ys)- | otherwise = return xs+connectionReadAtLeast = readAtLeast
src/Network/HTTP/Toolkit/Header.hs view
@@ -21,12 +21,12 @@ import Network.HTTP.Types import Network.HTTP.Toolkit.Error-import Network.HTTP.Toolkit.Connection+import Network.HTTP.Toolkit.InputStream -- | Message header size limit in bytes. type Limit = Int --- | Read start-line and message headers from provided `Connection`+-- | Read start-line and message headers from provided `InputStream` -- (see <http://tools.ietf.org/html/rfc2616#section-4.1 RFC 2616, Section 4.1>). -- -- Throws:@@ -34,7 +34,7 @@ -- * `HeaderTooLarge` if start-line and headers together exceed the specified size `Limit` -- -- * `InvalidHeader` if start-line is missing or a header is malformed-readMessageHeader :: Limit -> Connection -> IO (ByteString, [Header])+readMessageHeader :: Limit -> InputStream -> IO (ByteString, [Header]) readMessageHeader limit c = do hs <- readHeaderLines limit c maybe (throwIO InvalidHeader) return $ case hs of@@ -79,7 +79,7 @@ (_, y) -> let (ys, zs) = go xs in (stripEnd y : ys, zs) [] -> ([], []) -readHeaderLines :: Limit -> Connection -> IO [ByteString]+readHeaderLines :: Limit -> InputStream -> IO [ByteString] readHeaderLines n c = go n where go limit = do@@ -90,18 +90,18 @@ defaultHeaderSizeLimit :: Limit defaultHeaderSizeLimit = 64 * 1024 -readHeaderLine :: Connection -> Limit -> IO ByteString+readHeaderLine :: InputStream -> Limit -> IO ByteString readHeaderLine c = fmap stripCR . go where go limit = do when (limit < 0) (throwIO HeaderTooLarge)- bs <- connectionRead c+ bs <- readInput c case B.break (== '\n') bs of (xs, "") -> do ys <- go (limit - B.length xs) return (xs `B.append` ys) (xs, ys) -> do- connectionUnread c (B.drop 1 ys)+ unreadInput c (B.drop 1 ys) return xs stripCR bs | (not . B.null) bs && B.last bs == '\r' = B.init bs
+ src/Network/HTTP/Toolkit/InputStream.hs view
@@ -0,0 +1,62 @@+module Network.HTTP.Toolkit.InputStream (+ InputStream(..)+, makeInputStream+, inputStreamFromHandle+, readInput+, unreadInput+, readAtLeast+) where++import Prelude hiding (read)+import Control.Monad (join, when, unless)+import Control.Exception+import System.IO (Handle)+import Data.IORef+import Data.ByteString (ByteString)+import qualified Data.ByteString as B++import Network.HTTP.Toolkit.Error++-- | An abstraction for input streams that allows to read and unread input.+data InputStream = InputStream {+ _read :: IO ByteString+, _unread :: ByteString -> IO ()+}++-- | Create an `InputStream` from provided `Handle`.+inputStreamFromHandle :: Handle -> IO InputStream+inputStreamFromHandle h = makeInputStream (B.hGetSome h 4096)++-- | Create an `InputStream` from provided @IO@ action.+makeInputStream :: IO ByteString -> IO InputStream+makeInputStream read = do+ ref <- newIORef []+ return $ InputStream {+ _read = join $ atomicModifyIORef ref $ \xs -> case xs of+ y : ys -> (ys, return y)+ _ -> (xs, read)+ , _unread = \x -> atomicModifyIORef ref $ \xs -> (x : xs, ())+ }++-- | Read some input.+readInput :: InputStream -> IO ByteString+readInput c = do+ bs <- _read c+ when (B.null bs) $ throwIO UnexpectedEndOfInput+ return bs++-- | Push back some input. The pushed back input will be returned by a later+-- call to `readInput`.+unreadInput :: InputStream -> ByteString -> IO ()+unreadInput conn bs = unless (B.null bs) (_unread conn bs)++-- | Read at least the specified number of bytes from the input stream.+readAtLeast :: InputStream -> Int -> IO ByteString+readAtLeast conn n = readInput conn >>= go+ where+ go :: ByteString -> IO ByteString+ go xs+ | B.length xs < n = do+ ys <- readInput conn+ go (xs `B.append` ys)+ | otherwise = return xs
src/Network/HTTP/Toolkit/Request.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings, DeriveFunctor #-}+{-# LANGUAGE OverloadedStrings, DeriveFunctor, DeriveFoldable, DeriveTraversable #-} module Network.HTTP.Toolkit.Request ( RequestPath , Request(..)@@ -15,12 +15,14 @@ import Control.Applicative import Control.Exception import Data.Maybe+import Data.Foldable+import Data.Traversable import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import Network.HTTP.Types import Network.HTTP.Toolkit.Error-import Network.HTTP.Toolkit.Connection+import Network.HTTP.Toolkit.InputStream import Network.HTTP.Toolkit.Header import Network.HTTP.Toolkit.Body @@ -31,14 +33,16 @@ , requestPath :: RequestPath , requestHeaders :: [Header] , requestBody :: a-} deriving (Eq, Show, Functor)+} deriving (Eq, Show, Functor, Foldable, Traversable) -- | Same as `readRequestWithLimit` with a `Limit` of `defaultHeaderSizeLimit`.-readRequest :: Connection -> IO (Request BodyReader)+readRequest :: Bool -> InputStream -> IO (Request BodyReader) readRequest = readRequestWithLimit defaultHeaderSizeLimit --- | Read request from provided connection.+-- | Read request from provided `InputStream`. --+-- The second argument is passed to `makeChunkedReader`.+-- -- Throws: -- -- * `InvalidRequestLine` if request-line is malformed.@@ -46,11 +50,11 @@ -- * `HeaderTooLarge` if request-line and headers together exceed the specified size `Limit` -- -- * `InvalidHeader` if request-line is missing or a header is malformed-readRequestWithLimit :: Limit -> Connection -> IO (Request BodyReader)-readRequestWithLimit limit c = do+readRequestWithLimit :: Limit -> Bool -> InputStream -> IO (Request BodyReader)+readRequestWithLimit limit raw c = do (startLine, headers) <- readMessageHeader limit c (method, path) <- parseRequestLine_ startLine- Request method path headers <$> makeBodyReader c (determineRequestBodyType headers)+ Request method path headers <$> makeBodyReader raw (determineRequestBodyType headers) c parseRequestLine_ :: ByteString -> IO (Method, RequestPath) parseRequestLine_ input = maybe (throwIO $ InvalidRequestLine input) return (parseRequestLine input)
src/Network/HTTP/Toolkit/Response.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings, DeriveFunctor #-}+{-# LANGUAGE OverloadedStrings, DeriveFunctor, DeriveFoldable, DeriveTraversable #-} module Network.HTTP.Toolkit.Response ( Response(..) , readResponse@@ -17,12 +17,14 @@ import Control.Exception import Text.Read (readMaybe) import Data.Maybe+import Data.Foldable+import Data.Traversable import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import Network.HTTP.Types import Network.HTTP.Toolkit.Error-import Network.HTTP.Toolkit.Connection+import Network.HTTP.Toolkit.InputStream import Network.HTTP.Toolkit.Header import Network.HTTP.Toolkit.Body @@ -30,15 +32,17 @@ responseStatus :: Status , responseHeaders :: [Header] , responseBody :: a-} deriving (Eq, Show, Functor)+} deriving (Eq, Show, Functor, Foldable, Traversable) -- | Same as `readResponseWithLimit` with a `Limit` of -- `defaultHeaderSizeLimit`.-readResponse :: Method -> Connection -> IO (Response BodyReader)+readResponse :: Bool -> Method -> InputStream -> IO (Response BodyReader) readResponse = readResponseWithLimit defaultHeaderSizeLimit --- | Read response from provided connection.+-- | Read response from provided `InputStream`. --+-- The second argument is passed to `makeChunkedReader`.+-- -- The corresponding request `Method` has to be specified so that the body length can be determined (see -- <http://tools.ietf.org/html/rfc2616#section-4.4 RFC 2616, Section 4.4>). --@@ -49,11 +53,11 @@ -- * `HeaderTooLarge` if status-line and headers together exceed the specified size `Limit` -- -- * `InvalidHeader` if status-line is missing or a header is malformed-readResponseWithLimit :: Limit -> Method -> Connection -> IO (Response BodyReader)-readResponseWithLimit limit method c = do+readResponseWithLimit :: Limit -> Bool -> Method -> InputStream -> IO (Response BodyReader)+readResponseWithLimit limit raw method c = do (startLine, headers) <- readMessageHeader limit c status <- parseStatusLine_ startLine- Response status headers <$> makeBodyReader c (determineResponseBodyType method status headers)+ Response status headers <$> makeBodyReader raw (determineResponseBodyType method status headers) c parseStatusLine_ :: ByteString -> IO Status parseStatusLine_ input = maybe (throwIO $ InvalidStatusLine input) return (parseStatusLine input)