X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpleroma%2Fhttp%2Fhttp.ex;h=052597191fcc90d48641217f6002418462893031;hb=8bacdc36806efd01a7897359ff0fd2c8e24730d2;hp=ad47dc936f56ca60ed22705fefa2e06d79df3916;hpb=514c899275a32e6ef63305f9424c50344d41b12e;p=akkoma diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex index ad47dc936..052597191 100644 --- a/lib/pleroma/http/http.ex +++ b/lib/pleroma/http/http.ex @@ -1,5 +1,5 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.HTTP do @@ -7,7 +7,7 @@ defmodule Pleroma.HTTP do Wrapper for `Tesla.request/2`. """ - alias Pleroma.HTTP.Connection + alias Pleroma.HTTP.AdapterHelper alias Pleroma.HTTP.Request alias Pleroma.HTTP.RequestBuilder, as: Builder alias Tesla.Client @@ -16,6 +16,7 @@ defmodule Pleroma.HTTP do require Logger @type t :: __MODULE__ + @type method() :: :get | :post | :put | :delete | :head @doc """ Performs GET request. @@ -28,6 +29,9 @@ defmodule Pleroma.HTTP do def get(nil, _, _), do: nil def get(url, headers, options), do: request(:get, url, "", headers, options) + @spec head(Request.url(), Request.headers(), keyword()) :: {:ok, Env.t()} | {:error, any()} + def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options) + @doc """ Performs POST request. @@ -42,7 +46,7 @@ defmodule Pleroma.HTTP do Builds and performs http request. # Arguments: - `method` - :get, :post, :put, :delete + `method` - :get, :post, :put, :delete, :head `url` - full url `body` - request body `headers` - a keyworld list of headers, e.g. `[{"content-type", "text/plain"}]` @@ -52,86 +56,31 @@ defmodule Pleroma.HTTP do `{:ok, %Tesla.Env{}}` or `{:error, error}` """ - @spec request(atom(), Request.url(), String.t(), Request.headers(), keyword()) :: + @spec request(method(), Request.url(), String.t(), Request.headers(), keyword()) :: {:ok, Env.t()} | {:error, any()} def request(method, url, body, headers, options) when is_binary(url) do - with uri <- URI.parse(url), - received_adapter_opts <- Keyword.get(options, :adapter, []), - adapter_opts <- Connection.options(uri, received_adapter_opts), - options <- put_in(options[:adapter], adapter_opts), - params <- Keyword.get(options, :params, []), - request <- build_request(method, headers, options, url, body, params), - client <- Tesla.client([Tesla.Middleware.FollowRedirects], tesla_adapter()), - pid <- Process.whereis(adapter_opts[:pool]) do - pool_alive? = - if tesla_adapter() == Tesla.Adapter.Gun do - if pid, do: Process.alive?(pid), else: false - else - false - end - - request_opts = - adapter_opts - |> Enum.into(%{}) - |> Map.put(:env, Pleroma.Config.get([:env])) - |> Map.put(:pool_alive?, pool_alive?) - - response = - request( - client, - request, - request_opts - ) - - Connection.after_request(adapter_opts) - - response - end - end + uri = URI.parse(url) + adapter_opts = AdapterHelper.options(uri, options || []) - @spec request(Client.t(), keyword(), map()) :: {:ok, Env.t()} | {:error, any()} - def request(%Client{} = client, request, %{env: :test}), do: request_try(client, request) + options = put_in(options[:adapter], adapter_opts) + params = options[:params] || [] + request = build_request(method, headers, options, url, body, params) - def request(%Client{} = client, request, %{body_as: :chunks}) do - request_try(client, request) - end + adapter = Application.get_env(:tesla, :adapter) - def request(%Client{} = client, request, %{pool_alive?: false}) do - request_try(client, request) - end + client = Tesla.client(adapter_middlewares(adapter), adapter) - def request(%Client{} = client, request, %{pool: pool, timeout: timeout}) do - try do - :poolboy.transaction( - pool, - &Pleroma.Pool.Request.execute(&1, client, request, timeout + 500), - timeout + 1_000 - ) - rescue - e -> - {:error, e} - catch - :exit, {:timeout, _} -> - Logger.warn("Receive response from pool failed #{request[:url]}") - {:error, :recv_pool_timeout} - - :exit, e -> - {:error, e} - end + maybe_limit( + fn -> + request(client, request) + end, + adapter, + adapter_opts + ) end - @spec request_try(Client.t(), keyword()) :: {:ok, Env.t()} | {:error, any()} - def request_try(client, request) do - try do - Tesla.request(client, request) - rescue - e -> - {:error, e} - catch - :exit, e -> - {:error, e} - end - end + @spec request(Client.t(), keyword()) :: {:ok, Env.t()} | {:error, any()} + def request(client, request), do: Tesla.request(client, request) defp build_request(method, headers, options, url, body, params) do Builder.new() @@ -144,5 +93,18 @@ defmodule Pleroma.HTTP do |> Builder.convert_to_keyword() end - defp tesla_adapter, do: Application.get_env(:tesla, :adapter) + @prefix Pleroma.Gun.ConnectionPool + defp maybe_limit(fun, Tesla.Adapter.Gun, opts) do + ConcurrentLimiter.limit(:"#{@prefix}.#{opts[:pool] || :default}", fun) + end + + defp maybe_limit(fun, _, _) do + fun.() + end + + defp adapter_middlewares(Tesla.Adapter.Gun) do + [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.ConnectionPool] + end + + defp adapter_middlewares(_), do: [] end