benoitc / hackney

simple HTTP client in Erlang
Other
1.34k stars 427 forks source link

recv_timeout not respected when using a proxy to connect to a down host #569

Open dvgica opened 5 years ago

dvgica commented 5 years ago

Hello!

We are using hackney via httpoison, and routing all requests through a Squid proxy. There seems to be a bug when attempting to send a request to a host that is not accepting connections. Namely, neither a :timeout nor a :connect_timeout is returned. Instead, once the proxy itself times out and returns 503, a :proxy_error is returned.

Demo:

# where 123.123.123.123 is an IP address refusing connections on 443,
# and Squid is running at localhost:3128 with default configuration

iex(13)> :timer.tc(fn () -> :hackney.get("https://123.123.123.123", [], <<>>, []) end)                                
{8001522, {:error, :connect_timeout}}
iex(14)> :timer.tc(fn () -> :hackney.get("https://123.123.123.123", [], <<>>, [{:proxy, "http://localhost:3128"}]) end)
11:58:27.242 [][error] proxy error: "HTTP/1.1 503 Service Unavailable\r\nServer: squid/3.5.12\r\nMime-Version: 1.0\r\nDate: Fri, 24 May 2019 15:58:27 GMT\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: 3511\r\nX-Squid-Error: ERR_CONNECT_FAIL 110\r\nVary: Accept-Language\r\nContent-Language: en\r\n\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html><head>\n<meta type=\"copyright\" content=\"Copyright (C) 1996-2015 The Squid Software Foundation and contributors\">\n<meta http-equiv=\"Content-Type\" CONTENT=\"text/html; charset=utf-8\">\n<title>ERROR: The requested URL could not be retrieved</title>\n<style type=\"text/css\"><!-- \n /*\n * Copyright (C) 1996-2015 The Squid Software Foundation and contributors\n *\n * Squid software is distributed under GPLv2+ license and includes\n * contributions from numerous individuals and organizations.\n * Please see the COPYING and CONTRIBUTORS files for details.\n */\n\n/*\n Stylesheet for Squid Error pages\n Adapted from design by Free CSS Templates\n http://www.freecsstemplates.org\n Released for free under a Creative Commons Attribution 2.5 License\n*/\n\n/* Page basics */\n* {\n\tfont-family: verdana, sans-serif;\n}\n\nhtml body {\n\tmargin: 0;\n\tpadding: 0;\n\tbackground: #efefef;\n\tfont-size: 12px;\n\tcolor: #1e1e1e;\n}\n\n/* Page displayed title area */\n#titles {\n\tmargin-left: 15px;\n\tpadding: 10px;\n\tpadding-left: 100px;\n\tbackground: url('/squid-internal-static/icons/SN.png') no-repeat left;\n}\n\n/* initial title */\n#titles h1 {\n\tcolor:"

{60042305, {:error, :proxy_error}} # I expect {5000000, {:error, :timeout}} here instead

While it kind of makes sense that a :connect_timeout would not be returned (since the client can successfully connect to the proxy), I would expect to receive :timeout due to the recv_timeout option which is defaulted to 5 s. After all, no HTTP response is returned until 60 seconds have elapsed (the Squid timeout).

I note that the recv_timeout option does seem to work when the host can be connected to via the proxy.

This seems like a bug to me. We could work around it by setting the proxy timeout to the desired timeout, but it would be better to have hackney respect timeouts that are set. Thoughts?