diff --git a/lib/req.ex b/lib/req.ex index 81a29a2..2f7d4de 100644 --- a/lib/req.ex +++ b/lib/req.ex @@ -223,6 +223,8 @@ defmodule Req do * `string` - sets to this value. + * `&fun/0` - a function that returns one of the above (such as a `{:bearer, token}`). + Request body encoding options ([`encode_body`](`Req.Steps.encode_body/1`)): * `:form` - if set, encodes the request body as `application/x-www-form-urlencoded` diff --git a/lib/req/request.ex b/lib/req/request.ex index 06c94c2..4aa08a5 100644 --- a/lib/req/request.ex +++ b/lib/req/request.ex @@ -1256,6 +1256,10 @@ defmodule Req.Request do {:bearer, redact(bearer)} end + defp redact_option(:auth, fun) when is_function(fun, 0) do + fun + end + defp redact_option(:auth, {:basic, userinfo}) do {:basic, redact(userinfo)} end diff --git a/lib/req/steps.ex b/lib/req/steps.ex index ce6404f..33e332e 100644 --- a/lib/req/steps.ex +++ b/lib/req/steps.ex @@ -184,17 +184,23 @@ defmodule Req.Steps do * `{:netrc, path}` - load credentials from `path` + * `fn -> {:bearer, "eyJ0eXAi..." } end` - a 0-arity function that returns one of the aforementioned types. + ## Examples iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: {:basic, "foo:foo"}).status 401 iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: {:basic, "foo:bar"}).status 200 + iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: fn -> {:basic, "foo:bar"} end).status + 200 iex> Req.get!("https://httpbin.org/bearer", auth: {:bearer, ""}).status 401 iex> Req.get!("https://httpbin.org/bearer", auth: {:bearer, "foo"}).status 200 + iex> Req.get!("https://httpbin.org/bearer", auth: fn -> {:bearer, "foo"} end).status + 200 iex> System.put_env("NETRC", "./test/my_netrc") iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: :netrc).status @@ -202,6 +208,8 @@ defmodule Req.Steps do iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: {:netrc, "./test/my_netrc"}).status 200 + iex> Req.get!("https://httpbin.org/basic-auth/foo/bar", auth: fn -> {:netrc, "./test/my_netrc"} end).status + 200 """ @doc step: :request def auth(request) do @@ -224,6 +232,16 @@ defmodule Req.Steps do Req.Request.put_header(request, "authorization", "Bearer " <> token) end + defp auth(request, fun) when is_function(fun, 0) do + value = fun.() + + if is_function(value, 0) do + raise ArgumentError, "setting `auth: fn -> ... end` should not return another function" + end + + auth(request, value) + end + defp auth(request, :netrc) do path = System.get_env("NETRC") || Path.join(System.user_home!(), ".netrc") authenticate_with_netrc(request, path) diff --git a/test/req_test.exs b/test/req_test.exs index 85a6d55..b0a3970 100644 --- a/test/req_test.exs +++ b/test/req_test.exs @@ -56,6 +56,8 @@ defmodule ReqTest do assert inspect(Req.new(auth: {:basic, "foo:bar"})) =~ ~s|auth: {:basic, "foo****"}| + assert inspect(Req.new(auth: fn -> {:basic, "foo:bar"} end)) =~ ~s|auth: #Function| + if Req.MixProject.legacy_headers_as_lists?() do assert inspect(Req.new(headers: [authorization: "bearer foobar"])) =~ ~s|{"authorization", "bearer ***"}|