wreq icon indicating copy to clipboard operation
wreq copied to clipboard

Timeout only applies to the response headers

Open niteria opened this issue 5 years ago • 0 comments

Repro steps:

stack repl --package wreq
Prelude> import Network.Wreq
Prelude Network.Wreq> :set +s

# Quick request, no delays:
Prelude Network.Wreq> get "http://httpbin.org/drip?duration=0&numbytes=10&code=200&delay=0"
Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Date","Wed, 22 Jul 2020 20:13:46 GMT"),("Content-Type","application/octet-stream"),("Content-Length","10"),("Connection","keep-alive"),("Server","gunicorn/19.9.0"),("Access-Control-Allow-Origin","*"),("Access-Control-Allow-Credentials","true")], responseBody = "**********", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
(0.37 secs, 13,573,776 bytes)

# Request that takes 40s for the header to be produced and produces the body immediately (default timeout is 30s, so that's expected):
Prelude Network.Wreq> get "http://httpbin.org/drip?duration=0&numbytes=10&code=200&delay=40"
*** Exception: HttpExceptionRequest Request {
  host                 = "httpbin.org"
  port                 = 80
  secure               = False
  requestHeaders       = [("User-Agent","haskell wreq-0.5.3.2")]
  path                 = "/drip"
  queryString          = "?duration=0&numbytes=10&code=200&delay=40"
  method               = "GET"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
}
 ResponseTimeout

# Request that produces the header immediately and takes 60s 
# for the body to be produced (surprisingly, no timeout)
Prelude Network.Wreq> get "http://httpbin.org/drip?duration=60&numbytes=10&code=200&delay=0"
Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Date","Wed, 22 Jul 2020 20:17:05 GMT"),("Content-Type","application/octet-stream"),("Content-Length","10"),("Connection","keep-alive"),("Server","gunicorn/19.9.0"),("Access-Control-Allow-Origin","*"),("Access-Control-Allow-Credentials","true")], responseBody = "**********", responseCookieJar = 
CJ {expose = []}, responseClose' = ResponseClose}
(54.43 secs, 13,661,864 bytes)

AFAIK this is a behavior that was inherited from http-client, here's the correspoding issue: https://github.com/snoyberg/http-client/issues/416.

Maybe this is intended, but it surprised me and led to my app hanging every few weeks and quite extensive debugging before I wrapped get in System.Timeout.timeout.

niteria avatar Jul 22 '20 20:07 niteria