-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Req exits with :badarg when redirecting to invalid URL #327
Comments
Thank you for the report. I'm not sure if it's standardised but I believe skipping the scheme, In other words, if it's standardised (ideally in https://www.rfc-editor.org/rfc/rfc9110.html) that redirects without scheme should imply current scheme, we should fix it in Req. For example, if scheme and port is nil but host is set, fill them in. Could you investigate? |
The function iex(1)> URI.merge(URI.parse("https://good.url/"), URI.parse("//relative"))
%URI{
scheme: "https",
authority: "relative",
userinfo: nil,
host: "relative",
port: nil,
path: nil,
query: nil,
fragment: nil
}
Yes, RFC 9110 15.4 Redirection 3xx step 1 indicates that a relative However, RFC 3986 5.2 Relative Resolution doesn't seem to prescribe any steps for including the port in the merge steps. It looks like that's covered in RFC 3986 6.2.3 Scheme-Based Normalization, where the spec indicates an empty port should be assigned that of the default one for the scheme (as we would expect). Since the While something of the above will solve the nil port problem, we still experience issues with redirects where URI's contain characters that fail |
Something like the following solves the nil port problem: diff --git a/lib/req/steps.ex b/lib/req/steps.ex
index 712a8a5..222c28c 100644
--- a/lib/req/steps.ex
+++ b/lib/req/steps.ex
@@ -1964,7 +1964,10 @@ defmodule Req.Steps do
request.options[:redirect_trusted]
end
- location_url = URI.merge(request.url, URI.parse(location))
+ location_url =
+ request.url
+ |> URI.merge(URI.parse(location))
+ |> normalize_redirect_uri()
request
# assume put_params step already run so remove :params option so it's not applied again
@@ -1980,6 +1983,10 @@ defmodule Req.Steps do
Logger.log(level, ["redirecting to ", location])
end
+ defp normalize_redirect_uri(%URI{scheme: "http", port: nil} = uri), do: %URI{uri | port: 80}
+ defp normalize_redirect_uri(%URI{scheme: "https", port: nil} = uri), do: %URI{uri | port: 443}
+ defp normalize_redirect_uri(%URI{} = uri), do: uri
+
# https://www.rfc-editor.org/rfc/rfc9110#name-301-moved-permanently and 302:
#
# > Note: For historical reasons, a user agent MAY change the request method from |
…Finch from nil port - Fixes wojtekmach#327
This seems related sneako/finch#186 |
Fixed in #328 |
When redirect encounters an invalid URL, Req will exit with :badarg due to Finch exiting with the same. The following error is an example:
The request above fails after it redirects to
//muchong.com/html/201502/8544958.html
. As it turns out, AfterURI.merge/2
in Req.Steps.build_redirect_request/2 - the URL port may becomenil
if merged with relative scheme ("//somehost.com").In other words, the following triggers the failure:
And the following succeeds:
Initially I thought to just monkeypatch
URI.merge/2
, however, since there are other cases where it seems we're encountering invalid URLs, what I did internally for our use case was to add a URL validation step around line 2005 after the merge, and then halt the pipe with an error if there is an invalid URL.Another thought would be if we should just add a URL validation "step" instead of putting this into the redirect step explicitly.
Happy to submit a patch if that's acceptible for the library...
The text was updated successfully, but these errors were encountered: