diff --git a/changelog.d/hackney-proxy-ip-host.fix b/changelog.d/hackney-proxy-ip-host.fix new file mode 100644 index 000000000..5d11aadd5 --- /dev/null +++ b/changelog.d/hackney-proxy-ip-host.fix @@ -0,0 +1 @@ +Hackney: use the configured proxy when its host is an IP address; Hackney 4 ignored such proxies and connected directly \ No newline at end of file diff --git a/lib/pleroma/http/adapter_helper/hackney.ex b/lib/pleroma/http/adapter_helper/hackney.ex index 314f9e8b1..e9cc04361 100644 --- a/lib/pleroma/http/adapter_helper/hackney.ex +++ b/lib/pleroma/http/adapter_helper/hackney.ex @@ -30,6 +30,22 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do |> Pleroma.HTTP.AdapterHelper.maybe_add_proxy(proxy) |> Keyword.put(:follow_redirect, false) |> Keyword.put(:force_redirect, false) + |> normalize_proxy() + end + + # Hackney 4 ignores a proxy whose host is an IP tuple and connects directly. + # ConfigDB turns a numeric proxy host into such a tuple. + defp normalize_proxy(opts) do + case Keyword.fetch(opts, :proxy) do + {:ok, {type, host, port}} when is_tuple(host) -> + Keyword.put(opts, :proxy, {type, :inet.ntoa(host), port}) + + {:ok, {host, port}} when is_tuple(host) -> + Keyword.put(opts, :proxy, {:inet.ntoa(host), port}) + + _ -> + opts + end end defp add_scheme_opts(opts, _), do: opts diff --git a/test/pleroma/http/adapter_helper/hackney_test.exs b/test/pleroma/http/adapter_helper/hackney_test.exs index cf60d994b..22fcc93d1 100644 --- a/test/pleroma/http/adapter_helper/hackney_test.exs +++ b/test/pleroma/http/adapter_helper/hackney_test.exs @@ -39,6 +39,19 @@ defmodule Pleroma.HTTP.AdapterHelper.HackneyTest do assert opts[:proxy] == "localhost:8123" end + test "gives Hackney a string host for a proxy with an IP address", %{uri: uri} do + clear_config([:http, :proxy_url], {:socks5, {127, 0, 0, 1}, 9050}) + assert Hackney.options([], uri)[:proxy] == {:socks5, ~c"127.0.0.1", 9050} + + clear_config([:http, :proxy_url], {{10, 0, 0, 1}, 8123}) + assert Hackney.options([], uri)[:proxy] == {~c"10.0.0.1", 8123} + + clear_config([:http, :proxy_url], nil) + + assert Hackney.options([proxy: {:socks5, {0, 0, 0, 0, 0, 0, 0, 1}, 9050}], uri)[:proxy] == + {:socks5, ~c"::1", 9050} + end + test "respect connection opts and no proxy", %{uri: uri} do opts = Hackney.options([a: 2, b: 1], uri)