diff --git a/lib/req.ex b/lib/req.ex index fd9938de..7a11169d 100644 --- a/lib/req.ex +++ b/lib/req.ex @@ -149,6 +149,7 @@ defmodule Req do > For interopability with those, use > `Req.get_headers_list/1`. """ + require Logger # Response streaming to caller: # @@ -599,7 +600,7 @@ defmodule Req do request = Enum.reduce(request_options, request, fn {:url, url}, acc -> - put_in(acc.url, URI.parse(url)) + put_in(acc.url, parse_url(url)) {:headers, new_headers}, acc -> update_in(acc.headers, &Req.Fields.merge(&1, new_headers)) @@ -623,6 +624,24 @@ defmodule Req do ) end + defp parse_url(url) do + url = URI.parse(url) + + if url.userinfo do + Logger.warning(""" + non-empty url userinfo will be ignored. + + To use basic auth, use the :auth step: + + auth: {:basic, "user:password"} + """) + + %{url | userinfo: nil} + else + url + end + end + @doc """ Makes a GET request and returns a response or an error. diff --git a/test/req_test.exs b/test/req_test.exs index 2709b006..2db66180 100644 --- a/test/req_test.exs +++ b/test/req_test.exs @@ -65,6 +65,26 @@ defmodule ReqTest do assert headers == [{"x-a", "2"}, {"x-b", "1"}] end + test "warns and strips userinfo when set", c do + Bypass.expect(c.bypass, "GET", "/", fn conn -> + [user_agent] = Plug.Conn.get_req_header(conn, "user-agent") + Plug.Conn.send_resp(conn, 200, user_agent) + end) + + url = String.replace(c.url, "http://", "http://foo:bar@") + + assert ExUnit.CaptureLog.capture_log(fn -> + req = Req.new(url: url) + + # userinfo has been stripped + refute inspect(req) =~ "foo:bar@" + assert inspect(req) =~ c.url + + # request is sent without userinfo + assert Req.get!(req).status == 200 + end) =~ "[warning] non-empty url userinfo will be ignored" + end + test "redact" do assert inspect(Req.new(auth: {:bearer, "foo"})) =~ ~s|auth: {:bearer, "***"}|