diff options
author | rinpatch <rinpatch@sdf.org> | 2020-11-12 12:34:48 +0000 |
---|---|---|
committer | rinpatch <rinpatch@sdf.org> | 2020-11-12 12:34:48 +0000 |
commit | 1172844ed18d94d84724dc6f11c6e9f72e0ba6ec (patch) | |
tree | 7d48a259e08856ab6db0eba255f20c0c19410463 /lib/pleroma/http.ex | |
parent | a0f5e8b27edbe2224d9c2c3997ad5b8ea484244b (diff) | |
parent | b4c6b262d6dc12362f0014a864e8aed6c727c39c (diff) | |
download | pleroma-2.2.0.tar.gz |
Merge branch 'release/2.2.0' into 'stable'v2.2.0
Release/2.2.0
See merge request pleroma/secteam/pleroma!19
Diffstat (limited to 'lib/pleroma/http.ex')
-rw-r--r-- | lib/pleroma/http.ex | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex new file mode 100644 index 000000000..052597191 --- /dev/null +++ b/lib/pleroma/http.ex @@ -0,0 +1,110 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.HTTP do + @moduledoc """ + Wrapper for `Tesla.request/2`. + """ + + alias Pleroma.HTTP.AdapterHelper + alias Pleroma.HTTP.Request + alias Pleroma.HTTP.RequestBuilder, as: Builder + alias Tesla.Client + alias Tesla.Env + + require Logger + + @type t :: __MODULE__ + @type method() :: :get | :post | :put | :delete | :head + + @doc """ + Performs GET request. + + See `Pleroma.HTTP.request/5` + """ + @spec get(Request.url() | nil, Request.headers(), keyword()) :: + nil | {:ok, Env.t()} | {:error, any()} + def get(url, headers \\ [], options \\ []) + 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. + + See `Pleroma.HTTP.request/5` + """ + @spec post(Request.url(), String.t(), Request.headers(), keyword()) :: + {:ok, Env.t()} | {:error, any()} + def post(url, body, headers \\ [], options \\ []), + do: request(:post, url, body, headers, options) + + @doc """ + Builds and performs http request. + + # Arguments: + `method` - :get, :post, :put, :delete, :head + `url` - full url + `body` - request 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}` + + """ + @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 + uri = URI.parse(url) + adapter_opts = AdapterHelper.options(uri, options || []) + + options = put_in(options[:adapter], adapter_opts) + params = options[:params] || [] + request = build_request(method, headers, options, url, body, params) + + adapter = Application.get_env(:tesla, :adapter) + + client = Tesla.client(adapter_middlewares(adapter), adapter) + + maybe_limit( + fn -> + request(client, request) + end, + adapter, + adapter_opts + ) + 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() + |> Builder.method(method) + |> Builder.headers(headers) + |> Builder.opts(options) + |> Builder.url(url) + |> Builder.add_param(:body, :body, body) + |> Builder.add_param(:query, :query, params) + |> Builder.convert_to_keyword() + end + + @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 |