elixir-mint / mint

Functional HTTP client for Elixir with support for HTTP/1 and HTTP/2 🌱
Apache License 2.0
1.36k stars 106 forks source link

HTTP 407 error formatting when using proxies #439

Open jozuas opened 6 days ago

jozuas commented 6 days ago

Observed log:

** (Mint.HTTPError) expected tunnel proxy to return a status between 200 and 299, got: 407

Mint source code: https://github.com/elixir-mint/mint/blob/d3070089d4d22e8062e94df1334889437658fdee/lib/mint/tunnel_proxy.ex#L138

From MDN HTTP 407:

The HTTP 407 Proxy Authentication Required client error status response code indicates that the request has not been applied because it lacks valid authentication credentials for a proxy server that is between the browser and the server that can access the requested resource.

It would be nice to have nicely formatted error for HTTP 407 like with the other cases of https://github.com/elixir-mint/mint/blob/d3070089d4d22e8062e94df1334889437658fdee/lib/mint/tunnel_proxy.ex#L132-L147

jozuas commented 6 days ago

The more I'm looking at this ticket, the more unsure I am that it's worth changing anything. Sorry about the noise.

jozuas commented 6 days ago

To add to this, I observed that sometimes an unexpected info message after {:proxy, {:unexpected_status, 403}} or {:proxy, {:unexpected_status, 407}} ends up in the process that initiated the request.

Normally, I see something like this:

[warning] {:proxy, {:unexpected_status, 403}}, proxy: <<censored>>
[warning] retry: got exception, will retry in 1000ms, 3 attempts left
[warning] ** (Mint.HTTPError) expected tunnel proxy to return a status between 200 and 299, got: 403
[warning] {:proxy, {:unexpected_status, 407}}, proxy: <<censored>>
[warning] retry: got exception, will retry in 2000ms, 2 attempts left
[warning] ** (Mint.HTTPError) expected tunnel proxy to return a status between 200 and 299, got: 407
[warning] {:proxy, {:unexpected_status, 403}}, proxy: <<censored>>
[error] SomeGenServer: %Mint.HTTPError{reason: {:proxy, {:unexpected_status, 403}}, module: Mint.TunnelProxy}

But sometimese I observe this:

[warning] {:proxy, {:unexpected_status, 403}}, proxy: <<censored>>
[error] %Mint.HTTPError{reason: {:proxy, {:unexpected_status, 403}}, module: Mint.TunnelProxy}
[error] GenServer SomeGenServer terminating
** (FunctionClauseError) no function clause matching in SomeGenServer.handle_info/2
(tp 0.2.0) lib/some_gen_server.ex:153: XXX.handle_info({:tcp, #Port<0.662>, "org/*\">https://xxx.xxx/*</a></p>\n\n<blockquote id=\"error\">\n<p><b>Access Denied.</b></p>\n"}

This unexpected message sometimes happens in the background, but there does not seem to be a way to reliably trigger it for replication.

ericmj commented 6 days ago

I think the existing error message is quite clear, do you have a suggestion for how it can be improved?

The FunctionClauseError is not happening in Mint's code, it looks like you have a race condition in your GenServer.

jozuas commented 6 days ago

The FunctionClauseError is not happening in Mint's code, it looks like you have a race condition in your GenServer.

@ericmj the GenServer in question uses Req for making requests. Is it normal to get the lower-level messages from Mint in the process that makes requests with Req?

jozuas commented 6 days ago

I think the existing error message is quite clear, do you have a suggestion for how it can be improved?

You are completely correct, I realised this here https://github.com/elixir-mint/mint/issues/439#issuecomment-2191631194

ericmj commented 6 days ago

the GenServer in question uses Req for making requests. Is it normal to get the lower-level messages from Mint in the process that makes requests with Req?

No, that would be a finch or req issue. They need to keep handling tcp/ssl messages until the controlling process is changed or the connection is closed. The unexpected_status error does not mean the connection is closed.