Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/req.ex
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,16 @@ defmodule Req do
Finch options ([`run_finch`](`Req.Steps.run_finch/1`) step), see `Finch.start_link/1` for options:

* `:finch` - the Finch pool to use. Defaults to pool automatically started by `Req`.
Can be either a pool name (atom) or a `{name, opts}` tuple where `opts` can include:

* `:pool_tag` - the tag to use when selecting which Finch pool to use for a request.
Defaults to `:default`. This allows routing requests to different pools for the same
host. See `Finch.Pool.new/2` for more information on configuring tagged pools.

Examples:

Req.get!("https://api.example.com/data", finch: MyFinch)
Req.get!("https://api.example.com/data", finch: {MyFinch, pool_tag: :bulk})

* `:connect_options` - dynamically starts (or re-uses already started) Finch pool with
the given connection options (see `Mint.HTTP.connect/4` for options):
Expand Down
32 changes: 27 additions & 5 deletions lib/req/finch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ defmodule Req.Finch do
{:stream, enumerable}
end

build_opts = finch_build_opts(request)

finch_request =
Finch.build(request.method, request.url, request_headers, body)
|> Map.replace!(:unix_socket, request.options[:unix_socket])
Finch.build(request.method, request.url, request_headers, body, build_opts)
|> add_private_options(request.options[:finch_private])

finch_options =
Expand Down Expand Up @@ -411,16 +412,37 @@ defmodule Req.Finch do
end
end

defp finch_build_opts(request) do
pool_tag_opts =
case request.options[:finch] do
{_name, opts} when is_list(opts) ->
Keyword.take(opts, [:pool_tag])

_ ->
[]
end

unix_socket_opts =
request.options
|> Map.take([:unix_socket])
|> Enum.to_list()

pool_tag_opts ++ unix_socket_opts
end

defp finch_name(request) do
custom_options? =
Map.has_key?(request.options, :connect_options) or Map.has_key?(request.options, :inet6)

cond do
name = request.options[:finch] ->
finch_opt = request.options[:finch] ->
if Map.has_key?(request.options, :connect_options) do
raise ArgumentError, "cannot set both :finch and :connect_options"
else
name
end

case finch_opt do
{name, _opts} -> name
name -> name
end

custom_options? ->
Expand Down
10 changes: 10 additions & 0 deletions lib/req/steps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,16 @@ defmodule Req.Steps do
## Request Options

* `:finch` - the name of the Finch pool. Defaults to a pool automatically started by Req.
Can be either a pool name (atom) or a `{name, opts}` tuple where `opts` can include:

* `:pool_tag` - the tag to use when selecting which Finch pool to use for a request.
Defaults to `:default`. This allows routing requests to different pools for the same
host. See `Finch.Pool.new/2` for more information on configuring tagged pools.

Examples:

Req.get!("https://api.example.com/data", finch: MyFinch)
Req.get!("https://api.example.com/data", finch: {MyFinch, pool_tag: :bulk})

* `:connect_options` - dynamically starts (or re-uses already started) Finch pool with
the given connection options:
Expand Down
36 changes: 36 additions & 0 deletions test/req/finch_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -650,5 +650,41 @@ defmodule Req.FinchTest do
conn_opts: [transport_opts: [timeout: 0, inet6: true, cacerts: []]]
]
end

test ":pool_tag is forwarded to Finch request" do
%{url: url} =
start_http_server(fn conn ->
Plug.Conn.send_resp(conn, 200, "ok")
end)

pid = self()

fun = fn req, finch_request, finch_name, finch_opts ->
send(pid, {:pool_tag, finch_request.pool_tag})
{:ok, resp} = Finch.request(finch_request, finch_name, finch_opts)
{req, Req.Response.new(status: resp.status, headers: resp.headers, body: resp.body)}
end

assert Req.get!(url, finch_request: fun, finch: {Req.Finch, pool_tag: :bulk}).body == "ok"
assert_received {:pool_tag, :bulk}
end

test ":pool_tag defaults to :default" do
%{url: url} =
start_http_server(fn conn ->
Plug.Conn.send_resp(conn, 200, "ok")
end)

pid = self()

fun = fn req, finch_request, finch_name, finch_opts ->
send(pid, {:pool_tag, finch_request.pool_tag})
{:ok, resp} = Finch.request(finch_request, finch_name, finch_opts)
{req, Req.Response.new(status: resp.status, headers: resp.headers, body: resp.body)}
end

assert Req.get!(url, finch_request: fun).body == "ok"
assert_received {:pool_tag, :default}
end
end
end
Loading