http-client-brread-timeout 0.1.1.1 → 0.2.0.0
raw patch · 4 files changed
+67/−31 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.HTTP.Client.BrReadWithTimeout: brConsumeWithTimeout :: Int -> Request -> BodyReader -> IO [ByteString]
+ Network.HTTP.Client.BrReadWithTimeout: brReadSomeWithTimeout :: Int -> Request -> BodyReader -> Int -> IO ByteString
Files
- Changelog.md +4/−0
- Network/HTTP/Client/BrReadWithTimeout.hs +42/−13
- README.md +20/−17
- http-client-brread-timeout.cabal +1/−1
Changelog.md view
@@ -1,3 +1,7 @@+### 0.2.0.0++- Added functions *brReadSomeWithTimeout* and *brConsumeWithTimeout*.+ ### 0.1.1.1 - Refactor module imports.
Network/HTTP/Client/BrReadWithTimeout.hs view
@@ -18,23 +18,27 @@ ----------------------------------------------------------------------------- -module Network.HTTP.Client.BrReadWithTimeout (- fromResponseTimeout+module Network.HTTP.Client.BrReadWithTimeout (fromResponseTimeout ,brReadWithTimeout+ ,brReadSomeWithTimeout+ ,brConsumeWithTimeout ,httpLbsBrReadWithCustomTimeout ,httpLbsBrReadWithTimeout ) where import Network.HTTP.Client-import qualified Network.HTTP.Client.Internal as I (ResponseTimeout (..)- ,mResponseTimeout- )+import qualified Network.HTTP.Client.Internal+ as I (ResponseTimeout (..), mResponseTimeout) import Data.ByteString (ByteString) import qualified Data.ByteString.Lazy as L import Control.Exception import System.Timeout -- | Converts t'ResponseTimeout' of the request into the number of microseconds.+--+-- This function returns the value of the timeout on reading response headers+-- which can be used to apply equal timeouts between body read events in+-- `brReadWithTimeout`, `brReadSomeWithTimeout`, and `brConsumeWithTimeout`. fromResponseTimeout :: Request -> Manager -> Int fromResponseTimeout req man = case responseTimeout req of@@ -58,14 +62,39 @@ -- Throws v'ResponseTimeout' if reading of the next chunk of the response body -- timed out. brReadWithTimeout :: Int -> Request -> BodyReader -> IO ByteString-brReadWithTimeout tmo req br = do- x <- timeout tmo br- case x of- Nothing -> throwIO $ HttpExceptionRequest- req { responseTimeout = I.ResponseTimeoutMicro tmo }- ResponseTimeout- Just bs -> return bs+brReadWithTimeout tmo req br = timeout tmo br+ >>= maybe (throwIO $+ HttpExceptionRequest+ req { responseTimeout = I.ResponseTimeoutMicro tmo }+ ResponseTimeout+ ) return +-- | This is like 'brReadSome' but with a timeout between body read events.+--+-- The value of the timeout is passed in the first parameter as a number of+-- microseconds. A negative value effectively disables the timeout which makes+-- the function behave exactly as 'brReadSome'.+--+-- Implemented as `brReadSome` with `brReadWithTimeout` passed in its first+-- parameter.+--+-- @since 0.2.0.0+brReadSomeWithTimeout :: Int -> Request -> BodyReader -> Int -> IO L.ByteString+brReadSomeWithTimeout tmo req br = brReadSome $ brReadWithTimeout tmo req br++-- | This is like 'brConsume' but with a timeout between body read events.+--+-- The value of the timeout is passed in the first parameter as a number of+-- microseconds. A negative value effectively disables the timeout which makes+-- the function behave exactly as 'brConsume'.+--+-- Implemented as `brConsume` with `brReadWithTimeout` passed in its first+-- parameter.+--+-- @since 0.2.0.0+brConsumeWithTimeout :: Int -> Request -> BodyReader -> IO [ByteString]+brConsumeWithTimeout tmo req br = brConsume $ brReadWithTimeout tmo req br+ -- | This is like 'httpLbs' but with a timeout between body read events. -- -- The value of the timeout is passed in the first parameter as a number of@@ -74,7 +103,7 @@ httpLbsBrReadWithCustomTimeout :: Int -> Request -> Manager -> IO (Response L.ByteString) httpLbsBrReadWithCustomTimeout tmo req man = withResponse req man $ \res -> do- bss <- brConsume $ brReadWithTimeout tmo req $ responseBody res+ bss <- brConsumeWithTimeout tmo req $ responseBody res return res { responseBody = L.fromChunks bss } -- | This is like 'httpLbs' but with a timeout between body read events.
README.md view
@@ -15,6 +15,8 @@ A slow server can be emulated in *Nginx* with the following configuration. +##### nginx.conf+ ```nginx user nobody; worker_processes 2;@@ -50,18 +52,15 @@ } ``` -*GHCI* session.+##### GHCi REPL session (*cabal repl*). <pre>-<b>Prelude></b> import Network.HTTP.Client as HTTP.Client-<b>Prelude HTTP.Client></b> import Network.HTTP.Client.BrReadWithTimeout as BrReadWithTimeout-<b>Prelude HTTP.Client BrReadWithTimeout></b> httpManager = newManager defaultManagerSettings-<b>Prelude HTTP.Client BrReadWithTimeout></b> man <- httpManager-<b>Prelude HTTP.Client BrReadWithTimeout></b> reqVerySlow <- parseRequest "GET http://127.0.0.1:8010/very/slow"-<b>Prelude HTTP.Client BrReadWithTimeout></b> reqSlow <- parseRequest "GET http://127.0.0.1:8010/slow"-<b>Prelude HTTP.Client BrReadWithTimeout></b> :set +s-<b>Prelude HTTP.Client BrReadWithTimeout></b> httpLbs reqVerySlow man-Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Server","nginx/1.22.0"),("Date","Thu, 23 Jun 2022 22:04:02 GMT"),("Content-Type","application/octet-stream"),("Transfer-Encoding","chunked"),("Connection","keep-alive")], responseBody = "1\n2\n3\n4\n", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose, responseOriginalRequest = Request {+<b>*N.HTTP.C.BrReadWithTimeout></b> man <- newManager defaultManagerSettings+<b>*N.HTTP.C.BrReadWithTimeout></b> reqVerySlow <- parseRequest "GET http://127.0.0.1:8010/very/slow"+<b>*N.HTTP.C.BrReadWithTimeout></b> reqSlow <- parseRequest "GET http://127.0.0.1:8010/slow"+<b>*N.HTTP.C.BrReadWithTimeout></b> :set +s+<b>*N.HTTP.C.BrReadWithTimeout></b> httpLbs reqVerySlow man+Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Server","nginx/1.28.0"),("Date","Thu, 26 Feb 2026 13:33:38 GMT"),("Content-Type","application/octet-stream"),("Transfer-Encoding","chunked"),("Connection","keep-alive")], responseBody = "1\n2\n3\n4\n", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose, responseOriginalRequest = Request { host = "127.0.0.1" port = 8010 secure = False@@ -76,9 +75,9 @@ requestVersion = HTTP/1.1 proxySecureMode = ProxySecureWithConnect }-}-(80.09 secs, 1,084,840 bytes)-<b>Prelude HTTP.Client BrReadWithTimeout></b> httpLbsBrReadWithTimeout reqVerySlow man+, responseEarlyHints = []}+(80.08 secs, 1,266,728 bytes)+<b>*N.HTTP.C.BrReadWithTimeout></b> httpLbsBrReadWithTimeout reqVerySlow man *** Exception: HttpExceptionRequest Request { host = "127.0.0.1" port = 8010@@ -95,8 +94,12 @@ proxySecureMode = ProxySecureWithConnect } ResponseTimeout-<b>Prelude HTTP.Client BrReadWithTimeout></b> httpLbsBrReadWithTimeout reqSlow man-Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Server","nginx/1.22.0"),("Date","Thu, 23 Jun 2022 22:08:46 GMT"),("Content-Type","application/octet-stream"),("Transfer-Encoding","chunked"),("Connection","keep-alive")], responseBody = "1\n2\n3\n4\n", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose, responseOriginalRequest = Request {++HasCallStack backtrace:+ throwIO, called at ./Network/HTTP/Client/BrReadWithTimeout.hs:64:20 in http-client-brread-timeout-0.1.1.1-inplace:Network.HTTP.Client.BrReadWithTimeout++<b>*N.HTTP.C.BrReadWithTimeout></b> httpLbsBrReadWithTimeout reqSlow man+Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Server","nginx/1.28.0"),("Date","Thu, 26 Feb 2026 13:37:49 GMT"),("Content-Type","application/octet-stream"),("Transfer-Encoding","chunked"),("Connection","keep-alive")], responseBody = "1\n2\n3\n4\n", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose, responseOriginalRequest = Request { host = "127.0.0.1" port = 8010 secure = False@@ -111,8 +114,8 @@ requestVersion = HTTP/1.1 proxySecureMode = ProxySecureWithConnect }-}-(60.07 secs, 1,082,880 bytes)+, responseEarlyHints = []}+(60.05 secs, 1,261,728 bytes) </pre> Here, the first request comes from the standard `httpLbs` which, after timely
http-client-brread-timeout.cabal view
@@ -1,5 +1,5 @@ name: http-client-brread-timeout-version: 0.1.1.1+version: 0.2.0.0 synopsis: Http client with time-limited brRead description: Http client with timeouts applied in between body read events. .