Page MenuHomePhorge

No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/gun/connections.ex b/lib/pleroma/gun/connections.ex
index d5a9d8607..82579604a 100644
--- a/lib/pleroma/gun/connections.ex
+++ b/lib/pleroma/gun/connections.ex
@@ -1,125 +1,130 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Gun.Connections do
use GenServer
@type domain :: String.t()
@type conn :: Gun.Conn.t()
@type t :: %__MODULE__{
conns: %{domain() => conn()}
}
defstruct conns: %{}
def start_link(name \\ __MODULE__) do
if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
GenServer.start_link(__MODULE__, [], name: name)
else
:ignore
end
end
@impl true
def init(_) do
{:ok, %__MODULE__{conns: %{}}}
end
@spec get_conn(String.t(), keyword(), atom()) :: pid()
def get_conn(url, opts \\ [], name \\ __MODULE__) do
opts = Enum.into(opts, %{})
uri = URI.parse(url)
opts = if uri.scheme == "https", do: Map.put(opts, :transport, :tls), else: opts
GenServer.call(
name,
{:conn, %{opts: opts, uri: uri}}
)
end
# TODO: only for testing, add this parameter to the config
@spec try_to_get_gun_conn(String.t(), keyword(), atom()) :: nil | pid()
def try_to_get_gun_conn(url, opts \\ [], name \\ __MODULE__),
do: try_to_get_gun_conn(url, opts, name, 0)
@spec try_to_get_gun_conn(String.t(), keyword(), atom(), pos_integer()) :: nil | pid()
def try_to_get_gun_conn(_url, _, _, 3), do: nil
def try_to_get_gun_conn(url, opts, name, acc) do
case Pleroma.Gun.Connections.get_conn(url, opts, name) do
nil -> try_to_get_gun_conn(url, acc + 1)
conn -> conn
end
end
@spec alive?(atom()) :: boolean()
def alive?(name \\ __MODULE__) do
pid = Process.whereis(name)
if pid, do: Process.alive?(pid), else: false
end
@spec get_state(atom()) :: t()
def get_state(name \\ __MODULE__) do
GenServer.call(name, {:state})
end
@impl true
def handle_call({:conn, %{opts: opts, uri: uri}}, from, state) do
key = compose_key(uri)
+ IO.inspect(state)
+
+ IO.inspect(key)
+
case state.conns[key] do
%{conn: conn, state: conn_state} when conn_state == :up ->
{:reply, conn, state}
%{state: conn_state, waiting_pids: pids} when conn_state in [:open, :down] ->
state = put_in(state.conns[key].waiting_pids, [from | pids])
{:noreply, state}
nil ->
{:ok, conn} = Pleroma.Gun.API.open(to_charlist(uri.host), uri.port, opts)
state =
put_in(state.conns[key], %Pleroma.Gun.Conn{
conn: conn,
waiting_pids: [from],
protocol: String.to_atom(uri.scheme)
})
+ IO.inspect(state)
{:noreply, state}
end
end
@impl true
def handle_call({:state}, _from, state), do: {:reply, state, state}
@impl true
def handle_info({:gun_up, conn_pid, protocol}, state) do
{key, conn} = find_conn(state.conns, conn_pid, protocol)
# Send to all waiting processes connection pid
Enum.each(conn.waiting_pids, fn waiting_pid -> GenServer.reply(waiting_pid, conn_pid) end)
# Update state of the current connection and set waiting_pids to empty list
state = put_in(state.conns[key], %{conn | state: :up, waiting_pids: []})
{:noreply, state}
end
@impl true
# Do we need to do something with killed & unprocessed references?
def handle_info({:gun_down, conn_pid, protocol, _reason, _killed, _unprocessed}, state) do
{key, conn} = find_conn(state.conns, conn_pid, protocol)
# We don't want to block requests to GenServer if gun send down message, return nil, so we can make some retries, while connection is not up
Enum.each(conn.waiting_pids, fn waiting_pid -> GenServer.reply(waiting_pid, nil) end)
state = put_in(state.conns[key].state, :down)
{:noreply, state}
end
defp compose_key(uri), do: uri.host <> ":" <> to_string(uri.port)
defp find_conn(conns, conn_pid, protocol),
do: Enum.find(conns, fn {_, conn} -> conn.conn == conn_pid and conn.protocol == protocol end)
end
diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex
index 1846749c0..3ad891d11 100644
--- a/lib/pleroma/http/http.ex
+++ b/lib/pleroma/http/http.ex
@@ -1,109 +1,109 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP do
@moduledoc """
"""
alias Pleroma.HTTP.Connection
alias Pleroma.HTTP.RequestBuilder, as: Builder
@type t :: __MODULE__
@doc """
Builds and perform http request.
# Arguments:
`method` - :get, :post, :put, :delete
`url`
`body`
`headers` - a keyworld list of headers, e.g. `[{"content-type", "text/plain"}]`
`options` - custom, per-request middleware or adapter options
# Returns:
`{:ok, %Tesla.Env{}}` or `{:error, error}`
"""
def request(method, url, body \\ "", headers \\ [], options \\ []) do
try do
options =
process_request_options(options)
|> process_sni_options(url)
adapter_gun? = Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun
options =
if adapter_gun? and Pleroma.Gun.Connections.alive?() do
get_conn_for_gun(url, options)
else
options
end
params = Keyword.get(options, :params, [])
%{}
|> Builder.method(method)
|> Builder.headers(headers)
|> Builder.opts(options)
|> Builder.url(url)
|> Builder.add_param(:body, :body, body)
|> Builder.add_param(:query, :query, params)
|> Enum.into([])
|> (&Tesla.request(Connection.new(options), &1)).()
rescue
e ->
{:error, e}
catch
:exit, e ->
{:error, e}
end
end
defp get_conn_for_gun(url, options) do
- case Pleroma.Gun.Connections.try_to_get_gun_conn(url) do
+ case Pleroma.Gun.Connections.get_conn(url) do
nil ->
options
conn ->
adapter_opts =
Keyword.get(options, :adapter, [])
|> Keyword.put(:conn, conn)
Keyword.put(options, :adapter, adapter_opts)
end
end
defp process_sni_options(options, nil), do: options
defp process_sni_options(options, url) do
uri = URI.parse(url)
host = uri.host |> to_charlist()
case uri.scheme do
"https" -> options ++ [ssl: [server_name_indication: host]]
_ -> options
end
end
def process_request_options(options) do
Keyword.merge(Pleroma.HTTP.Connection.options([]), options)
end
@doc """
Performs GET request.
See `Pleroma.HTTP.request/5`
"""
def get(url, headers \\ [], options \\ []),
do: request(:get, url, "", headers, options)
@doc """
Performs POST request.
See `Pleroma.HTTP.request/5`
"""
def post(url, body, headers \\ [], options \\ []),
do: request(:post, url, body, headers, options)
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 10, 4:43 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1785358
Default Alt Text
(7 KB)

Event Timeline