config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
-config :pleroma, Pleroma.Gun.API, Pleroma.Gun.API.Mock
+config :pleroma, Pleroma.Gun, Pleroma.GunMock
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: true
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Gun.API do
- @callback open(charlist(), pos_integer(), map()) :: {:ok, pid()}
- @callback info(pid()) :: map()
- @callback close(pid()) :: :ok
- @callback await_up(pid, pos_integer()) :: {:ok, atom()} | {:error, atom()}
- @callback connect(pid(), map()) :: reference()
- @callback await(pid(), reference()) :: {:response, :fin, 200, []}
- @callback set_owner(pid(), pid()) :: :ok
+ @behaviour Pleroma.Gun
- def open(host, port, opts), do: api().open(host, port, opts)
+ alias Pleroma.Gun
- def info(pid), do: api().info(pid)
+ @gun_keys [
+ :connect_timeout,
+ :http_opts,
+ :http2_opts,
+ :protocols,
+ :retry,
+ :retry_timeout,
+ :trace,
+ :transport,
+ :tls_opts,
+ :tcp_opts,
+ :socks_opts,
+ :ws_opts
+ ]
- def close(pid), do: api().close(pid)
+ @impl Gun
+ def open(host, port, opts \\ %{}), do: :gun.open(host, port, Map.take(opts, @gun_keys))
- def await_up(pid, timeout \\ 5_000), do: api().await_up(pid, timeout)
+ @impl Gun
+ defdelegate info(pid), to: :gun
- def connect(pid, opts), do: api().connect(pid, opts)
+ @impl Gun
+ defdelegate close(pid), to: :gun
- def await(pid, ref), do: api().await(pid, ref)
+ @impl Gun
+ defdelegate await_up(pid, timeout \\ 5_000), to: :gun
- def set_owner(pid, owner), do: api().set_owner(pid, owner)
+ @impl Gun
+ defdelegate connect(pid, opts), to: :gun
- defp api, do: Pleroma.Config.get([Pleroma.Gun.API], Pleroma.Gun)
+ @impl Gun
+ defdelegate await(pid, ref), to: :gun
+
+ @impl Gun
+ defdelegate set_owner(pid, owner), to: :gun
end
@moduledoc """
Struct for gun connection data
"""
- alias Pleroma.Gun.API
+ alias Pleroma.Gun
alias Pleroma.Pool.Connections
require Logger
last_reference: :os.system_time(:second)
}
- :ok = API.set_owner(conn_pid, Process.whereis(name))
+ :ok = Gun.set_owner(conn_pid, Process.whereis(name))
Connections.add_conn(name, key, conn)
end
end
|> add_http2_opts(uri.scheme, Map.get(opts, :tls_opts, []))
with open_opts <- Map.delete(opts, :tls_opts),
- {:ok, conn} <- API.open(proxy_host, proxy_port, open_opts),
- {:ok, _} <- API.await_up(conn, opts[:await_up_timeout]),
- stream <- API.connect(conn, connect_opts),
- {:response, :fin, 200, _} <- API.await(conn, stream) do
+ {:ok, conn} <- Gun.open(proxy_host, proxy_port, open_opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]),
+ stream <- Gun.connect(conn, connect_opts),
+ {:response, :fin, 200, _} <- Gun.await(conn, stream) do
conn
else
error ->
|> Map.put(:protocols, [:socks])
|> Map.put(:socks_opts, socks_opts)
- with {:ok, conn} <- API.open(proxy_host, proxy_port, opts),
- {:ok, _} <- API.await_up(conn, opts[:await_up_timeout]) do
+ with {:ok, conn} <- Gun.open(proxy_host, proxy_port, opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]) do
conn
else
error ->
defp do_open(%URI{host: host, port: port} = uri, opts) do
host = Pleroma.HTTP.Connection.parse_host(host)
- with {:ok, conn} <- API.open(host, port, opts),
- {:ok, _} <- API.await_up(conn, opts[:await_up_timeout]) do
+ with {:ok, conn} <- Gun.open(host, port, opts),
+ {:ok, _} <- Gun.await_up(conn, opts[:await_up_timeout]) do
conn
else
error ->
with [{close_key, least_used} | _conns] <-
Connections.get_unused_conns(name),
- :ok <- Pleroma.Gun.API.close(least_used.conn) do
+ :ok <- Gun.close(least_used.conn) do
Connections.remove_conn(name, close_key)
do_open(uri, opts)
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Gun do
- @behaviour Pleroma.Gun.API
+ @callback open(charlist(), pos_integer(), map()) :: {:ok, pid()}
+ @callback info(pid()) :: map()
+ @callback close(pid()) :: :ok
+ @callback await_up(pid, pos_integer()) :: {:ok, atom()} | {:error, atom()}
+ @callback connect(pid(), map()) :: reference()
+ @callback await(pid(), reference()) :: {:response, :fin, 200, []}
+ @callback set_owner(pid(), pid()) :: :ok
- alias Pleroma.Gun.API
+ def open(host, port, opts), do: api().open(host, port, opts)
- @gun_keys [
- :connect_timeout,
- :http_opts,
- :http2_opts,
- :protocols,
- :retry,
- :retry_timeout,
- :trace,
- :transport,
- :tls_opts,
- :tcp_opts,
- :socks_opts,
- :ws_opts
- ]
+ def info(pid), do: api().info(pid)
- @impl API
- def open(host, port, opts \\ %{}), do: :gun.open(host, port, Map.take(opts, @gun_keys))
+ def close(pid), do: api().close(pid)
- @impl API
- defdelegate info(pid), to: :gun
+ def await_up(pid, timeout \\ 5_000), do: api().await_up(pid, timeout)
- @impl API
- defdelegate close(pid), to: :gun
+ def connect(pid, opts), do: api().connect(pid, opts)
- @impl API
- defdelegate await_up(pid, timeout \\ 5_000), to: :gun
+ def await(pid, ref), do: api().await(pid, ref)
- @impl API
- defdelegate connect(pid, opts), to: :gun
+ def set_owner(pid, owner), do: api().set_owner(pid, owner)
- @impl API
- defdelegate await(pid, ref), to: :gun
-
- @spec flush(pid() | reference()) :: :ok
- defdelegate flush(pid), to: :gun
-
- @impl API
- defdelegate set_owner(pid, owner), to: :gun
+ defp api, do: Pleroma.Config.get([Pleroma.Gun], Pleroma.Gun.API)
end
defstruct conns: %{}, opts: []
- alias Pleroma.Gun.API
+ alias Pleroma.Gun
@spec start_link({atom(), keyword()}) :: {:ok, pid()}
def start_link({name, opts}) do
nil ->
Logger.debug(":gun_up message for conn which is not found in state")
- :ok = API.close(conn_pid)
+ :ok = Gun.close(conn_pid)
state
end
{true, key} <- {Process.alive?(conn_pid), key} do
if conn.retries == retries do
Logger.debug("closing conn if retries is eq #{inspect(conn_pid)}")
- :ok = API.close(conn.conn)
+ :ok = Gun.close(conn.conn)
put_in(
state.conns,
nil ->
Logger.debug(":gun_down message for conn which is not found in state")
- :ok = API.close(conn_pid)
+ :ok = Gun.close(conn_pid)
state
end
defp compose_key_gun_info(pid) do
try do
# sometimes :gun.info can raise MatchError, which lead to pool terminate
- %{origin_host: origin_host, origin_scheme: scheme, origin_port: port} = API.info(pid)
+ %{origin_host: origin_host, origin_scheme: scheme, origin_port: port} = Gun.info(pid)
host =
case :inet.ntoa(origin_host) do
alias Pleroma.Pool.Connections
setup_all do
- {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.Gun.API.Mock)
+ {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.GunMock)
:ok
end
alias Pleroma.HTTP.Connection
setup_all do
- {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.Gun.API.Mock)
+ {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.GunMock)
:ok
end
describe "connection pools" do
@describetag :integration
- clear_config(Pleroma.Gun.API) do
- Pleroma.Config.put(Pleroma.Gun.API, Pleroma.Gun)
+ clear_config(Pleroma.Gun) do
+ Pleroma.Config.put(Pleroma.Gun, Pleroma.Gun.API)
end
test "gun" do
use ExUnit.Case
use Pleroma.Tests.Helpers
import ExUnit.CaptureLog
- alias Pleroma.Gun.API
alias Pleroma.Gun.Conn
alias Pleroma.Pool.Connections
setup_all do
- {:ok, _} = Registry.start_link(keys: :unique, name: API.Mock)
+ {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.GunMock)
:ok
end
describe "integration test" do
@describetag :integration
- clear_config(API) do
- Pleroma.Config.put(API, Pleroma.Gun)
+ clear_config(Pleroma.Gun) do
+ Pleroma.Config.put(Pleroma.Gun, Pleroma.Gun.API)
end
test "opens connection and change owner", %{name: name} do
alias Pleroma.ReverseProxy.Client
@moduletag :integration
- clear_config_all(Pleroma.Gun.API) do
- Pleroma.Config.put(Pleroma.Gun.API, Pleroma.Gun)
+ clear_config_all(Pleroma.Gun) do
+ Pleroma.Config.put(Pleroma.Gun, Pleroma.Gun.API)
end
setup do
Pleroma.Config.put(Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.Client.Tesla)
end
- clear_config(Pleroma.Gun.API) do
- Pleroma.Config.put(Pleroma.Gun.API, Pleroma.Gun)
+ clear_config(Pleroma.Gun) do
+ Pleroma.Config.put(Pleroma.Gun, Pleroma.Gun.API)
end
setup do
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Gun.API.Mock do
- @behaviour Pleroma.Gun.API
+defmodule Pleroma.GunMock do
+ @behaviour Pleroma.Gun
- alias Pleroma.Gun.API
+ alias Pleroma.Gun
+ alias Pleroma.GunMock
- @impl API
+ @impl Gun
def open('some-domain.com', 443, _) do
{:ok, conn_pid} = Task.start_link(fn -> Process.sleep(1_000) end)
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: "https",
origin_host: 'some-domain.com',
origin_port: 443
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open(ip, port, _)
when ip in [{10_755, 10_368, 61_708, 131, 64_206, 45_068, 0, 9_694}, {127, 0, 0, 1}] and
port in [80, 443] do
scheme = if port == 443, do: "https", else: "http"
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: scheme,
origin_host: ip,
origin_port: port
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open('localhost', 1234, %{
protocols: [:socks],
proxy: {:socks5, 'localhost', 1234},
}) do
{:ok, conn_pid} = Task.start_link(fn -> Process.sleep(1_000) end)
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: "http",
origin_host: 'proxy-socks.com',
origin_port: 80
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open('localhost', 1234, %{
protocols: [:socks],
proxy: {:socks4, 'localhost', 1234},
}) do
{:ok, conn_pid} = Task.start_link(fn -> Process.sleep(1_000) end)
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: "https",
origin_host: 'proxy-socks.com',
origin_port: 443
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open('gun-not-up.com', 80, _opts), do: {:error, :timeout}
- @impl API
+ @impl Gun
def open('example.com', port, _) when port in [443, 115] do
{:ok, conn_pid} = Task.start_link(fn -> Process.sleep(1_000) end)
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: "https",
origin_host: 'example.com',
origin_port: 443
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open(domain, 80, _) do
{:ok, conn_pid} = Task.start_link(fn -> Process.sleep(1_000) end)
- Registry.register(API.Mock, conn_pid, %{
+ Registry.register(GunMock, conn_pid, %{
origin_scheme: "http",
origin_host: domain,
origin_port: 80
{:ok, conn_pid}
end
- @impl API
+ @impl Gun
def open({127, 0, 0, 1}, 8123, _) do
Task.start_link(fn -> Process.sleep(1_000) end)
end
- @impl API
+ @impl Gun
def open('localhost', 9050, _) do
Task.start_link(fn -> Process.sleep(1_000) end)
end
- @impl API
+ @impl Gun
def await_up(_pid, _timeout), do: {:ok, :http}
- @impl API
+ @impl Gun
def set_owner(_pid, _owner), do: :ok
- @impl API
+ @impl Gun
def connect(pid, %{host: _, port: 80}) do
ref = make_ref()
- Registry.register(API.Mock, ref, pid)
+ Registry.register(GunMock, ref, pid)
ref
end
- @impl API
+ @impl Gun
def connect(pid, %{host: _, port: 443, protocols: [:http2], transport: :tls}) do
ref = make_ref()
- Registry.register(API.Mock, ref, pid)
+ Registry.register(GunMock, ref, pid)
ref
end
- @impl API
+ @impl Gun
def await(pid, ref) do
- [{_, ^pid}] = Registry.lookup(API.Mock, ref)
+ [{_, ^pid}] = Registry.lookup(GunMock, ref)
{:response, :fin, 200, []}
end
- @impl API
+ @impl Gun
def info(pid) do
- [{_, info}] = Registry.lookup(API.Mock, pid)
+ [{_, info}] = Registry.lookup(GunMock, pid)
info
end
- @impl API
+ @impl Gun
def close(_pid), do: :ok
end