From efec521daf8fa10d1ae4c9a2f18da01ba61bb5de Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Mon, 11 Oct 2021 20:41:38 -0300 Subject: [PATCH 01/11] allow unix sockets to be specified in pool configuration --- lib/finch.ex | 3 +++ test/finch_test.exs | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/finch.ex b/lib/finch.ex index dd7d31bc..b514ae63 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -133,6 +133,9 @@ defmodule Finch do :default -> {:ok, destination} + {:local, path} -> + {:ok, {:http, {:local, path}, 0}} + url when is_binary(url) -> cast_binary_destination(url) diff --git a/test/finch_test.exs b/test/finch_test.exs index 6a92e9fc..697506d2 100644 --- a/test/finch_test.exs +++ b/test/finch_test.exs @@ -75,18 +75,21 @@ defmodule FinchTest do %{bypass: bypass} do other_bypass = Bypass.open() default_bypass = Bypass.open() + unix_socket = {:local, "/my/unix/socket"} start_supervised!( {Finch, name: MyFinch, pools: %{ endpoint(bypass, "/some-path") => [count: 5, size: 5], - endpoint(other_bypass, "/some-other-path") => [count: 10, size: 10] + endpoint(other_bypass, "/some-other-path") => [count: 10, size: 10], + unix_socket => [count: 5, size: 5, conn_opts: [hostname: "localhost"]] }} ) assert get_pools(MyFinch, shp(bypass)) |> length() == 5 assert get_pools(MyFinch, shp(other_bypass)) |> length() == 10 + assert get_pools(MyFinch, shp(unix_socket)) |> length() == 5 # no pool has been started for this unconfigured shp assert get_pools(MyFinch, shp(default_bypass)) |> length() == 0 @@ -742,6 +745,7 @@ defmodule FinchTest do defp endpoint(%{port: port}, path \\ "/"), do: "http://localhost:#{port}#{path}" defp shp(%{port: port}), do: {:http, "localhost", port} + defp shp({:local, unix_socket}), do: {:http, {:local, unix_socket}, 0} defp expect_any(bypass) do Bypass.expect(bypass, fn conn -> Plug.Conn.send_resp(conn, 200, "OK") end) From e1abf0a43115d7bc3aa1a9a177cc2a3d50a74d3c Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Tue, 12 Oct 2021 13:54:05 -0300 Subject: [PATCH 02/11] create mock to use as an unix socket in tests --- test/support/mock_socket_server.ex | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 test/support/mock_socket_server.ex diff --git a/test/support/mock_socket_server.ex b/test/support/mock_socket_server.ex new file mode 100644 index 00000000..6b97b0d6 --- /dev/null +++ b/test/support/mock_socket_server.ex @@ -0,0 +1,52 @@ +defmodule Finch.MockSocketServer do + @moduledoc false + + @http_response "HTTP/1.1 200 OK\r\n\r\n" + + def start do + socket_address = build_socket_address() + delete_existing_sockets(socket_address) + + {:ok, socket} = listen(socket_address) + + spawn_link(fn -> + {:ok, client} = accept(socket) + + serve(client) + end) + + {:ok, socket_address} + end + + defp build_socket_address do + name = "finch_mock_socket_server.sock" + socket_path = System.tmp_dir!() |> Path.join(name) + + {:local, socket_path} + end + + defp delete_existing_sockets({:local, socket_path}) do + File.rm(socket_path) + end + + defp listen(socket_address) do + opts = [active: false, mode: :binary, packet: :raw, ifaddr: socket_address] + + :gen_tcp.listen(0, opts) + end + + defp accept(socket) do + {:ok, _client} = :gen_tcp.accept(socket) + end + + defp serve(client) do + case :gen_tcp.recv(client, 0) do + {:ok, _data} -> + :gen_tcp.send(client, @http_response) + :gen_tcp.close(client) + + _ -> + serve(client) + end + end +end From ce7aaed3fadecffc3ac4718c34111f1e4ca86ef1 Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Mon, 11 Oct 2021 19:33:22 -0300 Subject: [PATCH 03/11] add option to specify a unix socket when building a request --- lib/finch.ex | 14 +++++++++++--- lib/finch/request.ex | 8 +++++--- test/finch_test.exs | 20 +++++++++++++++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/finch.ex b/lib/finch.ex index b514ae63..05be19f4 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -201,7 +201,7 @@ defmodule Finch do where `body_stream` is a `Stream`. This feature is not yet supported for HTTP/2 requests. """ @spec build(Request.method(), Request.url(), Request.headers(), Request.body()) :: Request.t() - defdelegate build(method, url, headers \\ [], body \\ nil), to: Request + defdelegate build(method, url, headers \\ [], body \\ nil, opts \\ []), to: Request @doc """ Streams an HTTP request and returns the accumulator. @@ -230,11 +230,19 @@ defmodule Finch do {:ok, acc} | {:error, Exception.t()} when acc: term() def stream(%Request{} = req, name, acc, fun, opts \\ []) when is_function(fun, 2) do - %{scheme: scheme, host: host, port: port} = req - {pool, pool_mod} = PoolManager.get_pool(name, {scheme, host, port}) + shp = build_shp(req) + {pool, pool_mod} = PoolManager.get_pool(name, shp) pool_mod.request(pool, req, acc, fun, opts) end + defp build_shp(%Request{unix_socket: unix_socket}) when is_binary(unix_socket) do + {:http, {:local, unix_socket}, 0} + end + + defp build_shp(%Request{scheme: scheme, host: host, port: port}) do + {scheme, host, port} + end + @doc """ Sends an HTTP request and returns a `Finch.Response` struct. diff --git a/lib/finch/request.ex b/lib/finch/request.ex index 0fc129fc..02c4abd7 100644 --- a/lib/finch/request.ex +++ b/lib/finch/request.ex @@ -4,7 +4,7 @@ defmodule Finch.Request do """ @enforce_keys [:scheme, :host, :port, :method, :path, :headers, :body, :query] - defstruct [:scheme, :host, :port, :method, :path, :headers, :body, :query] + defstruct [:scheme, :host, :port, :method, :path, :headers, :body, :query, :unix_socket] @atom_methods [ :get, @@ -57,7 +57,8 @@ defmodule Finch.Request do def request_path(%{path: path, query: query}), do: "#{path}?#{query}" @doc false - def build(method, url, headers, body) do + def build(method, url, headers, body, opts) do + unix_socket = Keyword.get(opts, :unix_socket) {scheme, host, port, path, query} = parse_url(url) %Finch.Request{ @@ -68,7 +69,8 @@ defmodule Finch.Request do path: path, headers: headers, body: body, - query: query + query: query, + unix_socket: unix_socket } end diff --git a/test/finch_test.exs b/test/finch_test.exs index 697506d2..e9bd4051 100644 --- a/test/finch_test.exs +++ b/test/finch_test.exs @@ -3,6 +3,7 @@ defmodule FinchTest do doctest Finch alias Finch.Response + alias Finch.MockSocketServer setup do {:ok, bypass: Bypass.open()} @@ -148,7 +149,7 @@ defmodule FinchTest do end end - describe "build/4" do + describe "build/5" do test "raises if unsupported atom request method provided", %{bypass: bypass} do assert_raise ArgumentError, ~r/got unsupported atom method :gimme/, fn -> Finch.build(:gimme, endpoint(bypass)) @@ -258,6 +259,23 @@ defmodule FinchTest do assert {:ok, %{status: 200}} = Finch.build(:get, uri) |> Finch.request(MyFinch) end + test "successful get request when host is a unix socket" do + {:ok, socket_address} = MockSocketServer.start() + + start_supervised!( + {Finch, + name: MyFinch, + pools: %{ + socket_address => [conn_opts: [hostname: "localhost"]] + }} + ) + + {:local, socket_path} = socket_address + + Finch.build(:get, "http://localhost/", [], nil, unix_socket: socket_path) + |> Finch.request(MyFinch) + end + test "properly handles connection: close", %{bypass: bypass} do start_supervised!({Finch, name: MyFinch}) From 757568431bb55c648ba14f68bbc5b2a26b90511b Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Mon, 11 Oct 2021 19:35:56 -0300 Subject: [PATCH 04/11] update function arity in deprecation warning --- lib/finch.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/finch.ex b/lib/finch.ex index 05be19f4..c7af0ea3 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -285,7 +285,7 @@ defmodule Finch do end def request(name, method, url, headers, body \\ nil, opts \\ []) do - IO.warn("Finch.request/6 is deprecated, use Finch.build/4 + Finch.request/3 instead") + IO.warn("Finch.request/6 is deprecated, use Finch.build/5 + Finch.request/3 instead") build(method, url, headers, body) |> request(name, opts) From e6672976db990615e6b22bf2470130c2453c213e Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Thu, 14 Oct 2021 19:27:23 -0300 Subject: [PATCH 05/11] require scheme for unix socket in pool configuration --- lib/finch.ex | 8 ++++---- test/finch_test.exs | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/finch.ex b/lib/finch.ex index c7af0ea3..a12b919a 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -133,8 +133,8 @@ defmodule Finch do :default -> {:ok, destination} - {:local, path} -> - {:ok, {:http, {:local, path}, 0}} + {scheme, {:local, path}} when is_atom(scheme) and is_binary(path) -> + {:ok, {scheme, {:local, path}, 0}} url when is_binary(url) -> cast_binary_destination(url) @@ -235,8 +235,8 @@ defmodule Finch do pool_mod.request(pool, req, acc, fun, opts) end - defp build_shp(%Request{unix_socket: unix_socket}) when is_binary(unix_socket) do - {:http, {:local, unix_socket}, 0} + defp build_shp(%Request{scheme: scheme, unix_socket: unix_socket}) when is_binary(unix_socket) do + {scheme, {:local, unix_socket}, 0} end defp build_shp(%Request{scheme: scheme, host: host, port: port}) do diff --git a/test/finch_test.exs b/test/finch_test.exs index e9bd4051..c1a96d5c 100644 --- a/test/finch_test.exs +++ b/test/finch_test.exs @@ -84,13 +84,15 @@ defmodule FinchTest do pools: %{ endpoint(bypass, "/some-path") => [count: 5, size: 5], endpoint(other_bypass, "/some-other-path") => [count: 10, size: 10], - unix_socket => [count: 5, size: 5, conn_opts: [hostname: "localhost"]] + {:http, unix_socket} => [count: 5, size: 5, conn_opts: [hostname: "localhost"]], + {:https, unix_socket} => [count: 10, size: 10, conn_opts: [hostname: "localhost"]] }} ) assert get_pools(MyFinch, shp(bypass)) |> length() == 5 assert get_pools(MyFinch, shp(other_bypass)) |> length() == 10 - assert get_pools(MyFinch, shp(unix_socket)) |> length() == 5 + assert get_pools(MyFinch, shp({:http, unix_socket})) |> length() == 5 + assert get_pools(MyFinch, shp({:https, unix_socket})) |> length() == 10 # no pool has been started for this unconfigured shp assert get_pools(MyFinch, shp(default_bypass)) |> length() == 0 @@ -266,7 +268,7 @@ defmodule FinchTest do {Finch, name: MyFinch, pools: %{ - socket_address => [conn_opts: [hostname: "localhost"]] + {:http, socket_address} => [conn_opts: [hostname: "localhost"]] }} ) @@ -763,7 +765,7 @@ defmodule FinchTest do defp endpoint(%{port: port}, path \\ "/"), do: "http://localhost:#{port}#{path}" defp shp(%{port: port}), do: {:http, "localhost", port} - defp shp({:local, unix_socket}), do: {:http, {:local, unix_socket}, 0} + defp shp({scheme, {:local, unix_socket}}), do: {scheme, {:local, unix_socket}, 0} defp expect_any(bypass) do Bypass.expect(bypass, fn conn -> Plug.Conn.send_resp(conn, 200, "OK") end) From f1455cc3d98dad4ee8f311ce551daf62b6ba6979 Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Fri, 15 Oct 2021 07:39:30 -0300 Subject: [PATCH 06/11] refactor pool config to a pipeline --- lib/finch/pool_manager.ex | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/finch/pool_manager.ex b/lib/finch/pool_manager.ex index 484e95a9..011211b0 100644 --- a/lib/finch/pool_manager.ex +++ b/lib/finch/pool_manager.ex @@ -75,15 +75,14 @@ defmodule Finch.PoolManager do end defp pool_config(%{pools: config, default_pool_config: default}, shp) do - case Map.get(config, shp, config[:default]) do - nil -> maybe_drop_tls_options(shp, default) - config -> config - end + config + |> Map.get(shp, default) + |> maybe_drop_tls_options(shp) end # Drop TLS options from :conn_opts for default pools with :http scheme, # otherwise you will get :badarg error from :gen_tcp - defp maybe_drop_tls_options({:http, _, _} = _shp, config) when is_map(config) do + defp maybe_drop_tls_options(config, {:http, _, _} = _shp) when is_map(config) do with conn_opts when is_list(conn_opts) <- config[:conn_opts], trns_opts when is_list(trns_opts) <- conn_opts[:transport_opts] do trns_opts = Keyword.drop(trns_opts, @mint_tls_opts) @@ -94,7 +93,7 @@ defmodule Finch.PoolManager do end end - defp maybe_drop_tls_options(_, config), do: config + defp maybe_drop_tls_options(config, _), do: config defp pool_mod(:http1), do: Finch.HTTP1.Pool defp pool_mod(:http2), do: Finch.HTTP2.Pool From 74fc610539b568c6fb7d7fb23a607a264018ce3b Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Fri, 15 Oct 2021 07:40:19 -0300 Subject: [PATCH 07/11] add default hostname to unix socket pools --- lib/finch/pool_manager.ex | 14 ++++++++++++++ test/finch_test.exs | 16 ++++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/finch/pool_manager.ex b/lib/finch/pool_manager.ex index 011211b0..82a2d28b 100644 --- a/lib/finch/pool_manager.ex +++ b/lib/finch/pool_manager.ex @@ -8,6 +8,8 @@ defmodule Finch.PoolManager do :versions ] + @default_conn_hostname "localhost" + def start_link(config) do GenServer.start_link(__MODULE__, config, name: config.manager_name) end @@ -78,6 +80,7 @@ defmodule Finch.PoolManager do config |> Map.get(shp, default) |> maybe_drop_tls_options(shp) + |> maybe_add_hostname(shp) end # Drop TLS options from :conn_opts for default pools with :http scheme, @@ -95,6 +98,17 @@ defmodule Finch.PoolManager do defp maybe_drop_tls_options(config, _), do: config + # Hostname is required when the address is not a url (binary) so we need to specify + # a default value in case the configuration does not specify one. + defp maybe_add_hostname(config, {_scheme, {:local, _path}, _port} = _shp) when is_map(config) do + conn_opts = + config |> Map.get(:conn_opts, []) |> Keyword.put_new(:hostname, @default_conn_hostname) + + Map.put(config, :conn_opts, conn_opts) + end + + defp maybe_add_hostname(config, _), do: config + defp pool_mod(:http1), do: Finch.HTTP1.Pool defp pool_mod(:http2), do: Finch.HTTP2.Pool end diff --git a/test/finch_test.exs b/test/finch_test.exs index c1a96d5c..7d5831b0 100644 --- a/test/finch_test.exs +++ b/test/finch_test.exs @@ -84,8 +84,8 @@ defmodule FinchTest do pools: %{ endpoint(bypass, "/some-path") => [count: 5, size: 5], endpoint(other_bypass, "/some-other-path") => [count: 10, size: 10], - {:http, unix_socket} => [count: 5, size: 5, conn_opts: [hostname: "localhost"]], - {:https, unix_socket} => [count: 10, size: 10, conn_opts: [hostname: "localhost"]] + {:http, unix_socket} => [count: 5, size: 5], + {:https, unix_socket} => [count: 10, size: 10] }} ) @@ -262,17 +262,9 @@ defmodule FinchTest do end test "successful get request when host is a unix socket" do - {:ok, socket_address} = MockSocketServer.start() - - start_supervised!( - {Finch, - name: MyFinch, - pools: %{ - {:http, socket_address} => [conn_opts: [hostname: "localhost"]] - }} - ) + start_supervised!({Finch, name: MyFinch}) - {:local, socket_path} = socket_address + {:ok, {:local, socket_path}} = MockSocketServer.start() Finch.build(:get, "http://localhost/", [], nil, unix_socket: socket_path) |> Finch.request(MyFinch) From 523566377f291962a99fa703ac3d562875c25b4f Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Fri, 15 Oct 2021 08:43:00 -0300 Subject: [PATCH 08/11] add ssl capability to mock socket server --- test/support/mock_socket_server.ex | 65 +++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/test/support/mock_socket_server.ex b/test/support/mock_socket_server.ex index 6b97b0d6..22423729 100644 --- a/test/support/mock_socket_server.ex +++ b/test/support/mock_socket_server.ex @@ -1,18 +1,35 @@ defmodule Finch.MockSocketServer do @moduledoc false + @fixtures_dir Path.expand("../fixtures", __DIR__) + + @socket_opts [ + active: false, + mode: :binary, + packet: :raw + ] + + @ssl_opts [ + reuseaddr: true, + nodelay: true, + certfile: Path.join([@fixtures_dir, "selfsigned.pem"]), + keyfile: Path.join([@fixtures_dir, "selfsigned_key.pem"]) + ] + @http_response "HTTP/1.1 200 OK\r\n\r\n" - def start do + def start(opts \\ []) do + ssl? = Keyword.get(opts, :ssl?, false) + socket_address = build_socket_address() delete_existing_sockets(socket_address) - {:ok, socket} = listen(socket_address) + {:ok, socket} = listen(socket_address, ssl?) spawn_link(fn -> - {:ok, client} = accept(socket) + {:ok, client} = accept(socket, ssl?) - serve(client) + serve(client, ssl?) end) {:ok, socket_address} @@ -29,24 +46,54 @@ defmodule Finch.MockSocketServer do File.rm(socket_path) end - defp listen(socket_address) do - opts = [active: false, mode: :binary, packet: :raw, ifaddr: socket_address] + defp listen(socket_address, false = _ssl?) do + opts = [{:ifaddr, socket_address} | @socket_opts] :gen_tcp.listen(0, opts) end - defp accept(socket) do + defp listen(socket_address, true = _ssl?) do + base_opts = @socket_opts ++ @ssl_opts + opts = [{:ifaddr, socket_address} | base_opts] + + :ssl.listen(0, opts) + end + + defp accept(socket, false = _ssl?) do {:ok, _client} = :gen_tcp.accept(socket) end - defp serve(client) do + defp accept(socket, true = _ssl?) do + {:ok, client} = :ssl.transport_accept(socket) + + if function_exported?(:ssl, :handshake, 1) do + {:ok, _} = apply(:ssl, :handshake, [client]) + else + :ok = apply(:ssl, :ssl_accept, [client]) + end + + {:ok, client} + end + + defp serve(client, false = ssl?) do case :gen_tcp.recv(client, 0) do {:ok, _data} -> :gen_tcp.send(client, @http_response) :gen_tcp.close(client) _ -> - serve(client) + serve(client, ssl?) + end + end + + defp serve(client, true = ssl?) do + case :ssl.recv(client, 0) do + {:ok, _data} -> + :ssl.send(client, @http_response) + :ssl.close(client) + + _ -> + serve(client, ssl?) end end end From 6d1c54b7bf75d1c36bad18b6cdd4ebf9e6bbb4f7 Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Fri, 15 Oct 2021 09:02:06 -0300 Subject: [PATCH 09/11] ensure that requests can be made to unix sockets with https scheme --- test/finch_test.exs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/test/finch_test.exs b/test/finch_test.exs index 7d5831b0..db8127f3 100644 --- a/test/finch_test.exs +++ b/test/finch_test.exs @@ -261,13 +261,31 @@ defmodule FinchTest do assert {:ok, %{status: 200}} = Finch.build(:get, uri) |> Finch.request(MyFinch) end - test "successful get request when host is a unix socket" do + test "successful get request to a unix socket" do + {:ok, {:local, socket_path}} = MockSocketServer.start() + start_supervised!({Finch, name: MyFinch}) - {:ok, {:local, socket_path}} = MockSocketServer.start() + assert {:ok, %Response{status: 200}} = + Finch.build(:get, "http://localhost/", [], nil, unix_socket: socket_path) + |> Finch.request(MyFinch) + end + + @tag :capture_log + test "successful get request to a unix socket with tls" do + {:ok, socket_address = {:local, socket_path}} = MockSocketServer.start(ssl?: true) + + start_supervised!( + {Finch, + name: MyFinch, + pools: %{ + {:https, socket_address} => [conn_opts: [transport_opts: [verify: :verify_none]]] + }} + ) - Finch.build(:get, "http://localhost/", [], nil, unix_socket: socket_path) - |> Finch.request(MyFinch) + assert {:ok, %Response{status: 200}} = + Finch.build(:get, "https://localhost/", [], nil, unix_socket: socket_path) + |> Finch.request(MyFinch) end test "properly handles connection: close", %{bypass: bypass} do From 6cab10ce22e4ea272e3b9bce669d353b36f79d5b Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Mon, 11 Oct 2021 21:22:49 -0300 Subject: [PATCH 10/11] add documentation to configure a pool for an unix socket --- lib/finch.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/finch.ex b/lib/finch.ex index a12b919a..ca88a201 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -79,9 +79,10 @@ defmodule Finch do * `:name` - The name of your Finch instance. This field is required. * `:pools` - A map specifying the configuration for your pools. The keys should be URLs - provided as binaries, or the atom `:default` to provide a catch-all configuration to be used - for any unspecified URLs. See "Pool Configuration Options" below for details on the possible - map values. Default value is `%{default: [size: #{@default_pool_size}, count: #{@default_pool_count}]}`. + provided as binaries, a tuple `{:local, unix_socket}` where `unix_socket` is the path for + the socket, or the atom `:default` to provide a catch-all configuration to be used for any + unspecified URLs. See "Pool Configuration Options" below for details on the possible map + values. Default value is `%{default: [size: #{@default_pool_size}, count: #{@default_pool_count}]}`. ### Pool Configuration Options From 976f6f89eab121ee68e8e5b5ae703da38ca60039 Mon Sep 17 00:00:00 2001 From: Calvin Gerling Date: Fri, 15 Oct 2021 12:44:10 -0300 Subject: [PATCH 11/11] update pool configuration documentation Co-authored-by: Wojtek Mach --- lib/finch.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/finch.ex b/lib/finch.ex index ca88a201..fa246d4e 100644 --- a/lib/finch.ex +++ b/lib/finch.ex @@ -79,7 +79,7 @@ defmodule Finch do * `:name` - The name of your Finch instance. This field is required. * `:pools` - A map specifying the configuration for your pools. The keys should be URLs - provided as binaries, a tuple `{:local, unix_socket}` where `unix_socket` is the path for + provided as binaries, a tuple `{scheme, {:local, unix_socket}}` where `unix_socket` is the path for the socket, or the atom `:default` to provide a catch-all configuration to be used for any unspecified URLs. See "Pool Configuration Options" below for details on the possible map values. Default value is `%{default: [size: #{@default_pool_size}, count: #{@default_pool_count}]}`.