logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

http.ex (3570B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.HTTP do
  5. @moduledoc """
  6. Wrapper for `Tesla.request/2`.
  7. """
  8. alias Pleroma.HTTP.AdapterHelper
  9. alias Pleroma.HTTP.Request
  10. alias Pleroma.HTTP.RequestBuilder, as: Builder
  11. alias Tesla.Client
  12. alias Tesla.Env
  13. require Logger
  14. @type t :: __MODULE__
  15. @type method() :: :get | :post | :put | :delete | :head
  16. @doc """
  17. Performs GET request.
  18. See `Pleroma.HTTP.request/5`
  19. """
  20. @spec get(Request.url() | nil, Request.headers(), keyword()) ::
  21. nil | {:ok, Env.t()} | {:error, any()}
  22. def get(url, headers \\ [], options \\ [])
  23. def get(nil, _, _), do: nil
  24. def get(url, headers, options), do: request(:get, url, "", headers, options)
  25. @spec head(Request.url(), Request.headers(), keyword()) :: {:ok, Env.t()} | {:error, any()}
  26. def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options)
  27. @doc """
  28. Performs POST request.
  29. See `Pleroma.HTTP.request/5`
  30. """
  31. @spec post(Request.url(), String.t(), Request.headers(), keyword()) ::
  32. {:ok, Env.t()} | {:error, any()}
  33. def post(url, body, headers \\ [], options \\ []),
  34. do: request(:post, url, body, headers, options)
  35. @doc """
  36. Builds and performs http request.
  37. # Arguments:
  38. `method` - :get, :post, :put, :delete, :head
  39. `url` - full url
  40. `body` - request body
  41. `headers` - a keyworld list of headers, e.g. `[{"content-type", "text/plain"}]`
  42. `options` - custom, per-request middleware or adapter options
  43. # Returns:
  44. `{:ok, %Tesla.Env{}}` or `{:error, error}`
  45. """
  46. @spec request(method(), Request.url(), String.t(), Request.headers(), keyword()) ::
  47. {:ok, Env.t()} | {:error, any()}
  48. def request(method, url, body, headers, options) when is_binary(url) do
  49. uri = URI.parse(url)
  50. adapter_opts = AdapterHelper.options(uri, options || [])
  51. options = put_in(options[:adapter], adapter_opts)
  52. params = options[:params] || []
  53. request = build_request(method, headers, options, url, body, params)
  54. adapter = Application.get_env(:tesla, :adapter)
  55. client = Tesla.client(adapter_middlewares(adapter), adapter)
  56. maybe_limit(
  57. fn ->
  58. request(client, request)
  59. end,
  60. adapter,
  61. adapter_opts
  62. )
  63. end
  64. @spec request(Client.t(), keyword()) :: {:ok, Env.t()} | {:error, any()}
  65. def request(client, request), do: Tesla.request(client, request)
  66. defp build_request(method, headers, options, url, body, params) do
  67. Builder.new()
  68. |> Builder.method(method)
  69. |> Builder.headers(headers)
  70. |> Builder.opts(options)
  71. |> Builder.url(url)
  72. |> Builder.add_param(:body, :body, body)
  73. |> Builder.add_param(:query, :query, params)
  74. |> Builder.convert_to_keyword()
  75. end
  76. @prefix Pleroma.Gun.ConnectionPool
  77. defp maybe_limit(fun, Tesla.Adapter.Gun, opts) do
  78. ConcurrentLimiter.limit(:"#{@prefix}.#{opts[:pool] || :default}", fun)
  79. end
  80. defp maybe_limit(fun, _, _) do
  81. fun.()
  82. end
  83. defp adapter_middlewares(Tesla.Adapter.Gun) do
  84. [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.ConnectionPool]
  85. end
  86. defp adapter_middlewares({Tesla.Adapter.Finch, _}) do
  87. [Tesla.Middleware.FollowRedirects]
  88. end
  89. defp adapter_middlewares(_) do
  90. if Pleroma.Config.get(:env) == :test do
  91. # Emulate redirects in test env, which are handled by adapters in other environments
  92. [Tesla.Middleware.FollowRedirects]
  93. else
  94. []
  95. end
  96. end
  97. end