Skip to content

Commit 1718f56

Browse files
committed
Retreat userinfo as basic auth if present in URL
1 parent 923aacf commit 1718f56

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

lib/req.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,14 @@ defmodule Req do
599599
request =
600600
Enum.reduce(request_options, request, fn
601601
{:url, url}, acc ->
602-
put_in(acc.url, URI.parse(url))
602+
case URI.parse(url) do
603+
uri when is_binary(uri.userinfo) ->
604+
acc = put_in(acc.url, %{uri | userinfo: nil})
605+
update_in(acc.options, &Map.put_new(&1, :auth, {:basic, uri.userinfo}))
606+
607+
uri ->
608+
put_in(acc.url, uri)
609+
end
603610

604611
{:headers, new_headers}, acc ->
605612
update_in(acc.headers, &Req.Fields.merge(&1, new_headers))

test/req_test.exs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,31 @@ defmodule ReqTest do
6565
assert headers == [{"x-a", "2"}, {"x-b", "1"}]
6666
end
6767

68+
test "respects userinfo in URL", c do
69+
pid = self()
70+
71+
Bypass.expect(c.bypass, "GET", "/", fn conn ->
72+
case List.keyfind(conn.req_headers, "authorization", 0) do
73+
{_, auth_header} -> send(pid, {:authorization, auth_header})
74+
_ -> nil
75+
end
76+
77+
Plug.Conn.send_resp(conn, 200, "ok")
78+
end)
79+
80+
with_userinfo = String.replace(c.url, "http://", "http://foo:bar@")
81+
Req.get!(with_userinfo)
82+
assert_receive {:authorization, "Basic " <> _}
83+
84+
# explicit :auth option is favored over userinfo in URL
85+
Req.get!(with_userinfo, auth: {:bearer, "token"})
86+
assert_receive {:authorization, "Bearer token"}
87+
88+
req = Req.new(auth: {:bearer, "token"})
89+
Req.get!(req, url: with_userinfo)
90+
assert_receive {:authorization, "Bearer token"}
91+
end
92+
6893
test "redact" do
6994
assert inspect(Req.new(auth: {:bearer, "foo"})) =~ ~s|auth: {:bearer, "***"}|
7095

0 commit comments

Comments
 (0)