Skip to content

Commit

Permalink
auth: Support passing a 0-arity function (#417)
Browse files Browse the repository at this point in the history
  • Loading branch information
chgeuer authored Oct 7, 2024
1 parent ad18d19 commit c789ff9
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/req.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
4 changes: 4 additions & 0 deletions lib/req/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions lib/req/steps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -184,24 +184,32 @@ 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
200
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
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions test/req_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ***"}|
Expand Down

0 comments on commit c789ff9

Please sign in to comment.