First
[anni] / lib / pleroma / http / request_builder.ex
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
5 defmodule Pleroma.HTTP.RequestBuilder do
6   @moduledoc """
7   Helper functions for building Tesla requests
8   """
9
10   alias Pleroma.HTTP.Request
11   alias Tesla.Multipart
12
13   @doc """
14   Creates new request
15   """
16   @spec new(Request.t()) :: Request.t()
17   def new(%Request{} = request \\ %Request{}), do: request
18
19   @doc """
20   Specify the request method when building a request
21   """
22   @spec method(Request.t(), Request.method()) :: Request.t()
23   def method(request, m), do: %{request | method: m}
24
25   @doc """
26   Specify the request method when building a request
27   """
28   @spec url(Request.t(), Request.url()) :: Request.t()
29   def url(request, u), do: %{request | url: u}
30
31   @doc """
32   Add headers to the request
33   """
34   @spec headers(Request.t(), Request.headers()) :: Request.t()
35   def headers(request, headers) do
36     headers_list =
37       with true <- Pleroma.Config.get([:http, :send_user_agent]),
38            nil <- Enum.find(headers, fn {key, _val} -> String.downcase(key) == "user-agent" end) do
39         [{"user-agent", Pleroma.Application.user_agent()} | headers]
40       else
41         _ ->
42           headers
43       end
44
45     %{request | headers: headers_list}
46   end
47
48   @doc """
49   Add custom, per-request middleware or adapter options to the request
50   """
51   @spec opts(Request.t(), keyword()) :: Request.t()
52   def opts(request, options), do: %{request | opts: options}
53
54   @doc """
55   Add optional parameters to the request
56   """
57   @spec add_param(Request.t(), atom(), atom(), any()) :: Request.t()
58   def add_param(request, :query, :query, values), do: %{request | query: values}
59
60   def add_param(request, :body, :body, value), do: %{request | body: value}
61
62   def add_param(request, :body, key, value) do
63     request
64     |> Map.put(:body, Multipart.new())
65     |> Map.update!(
66       :body,
67       &Multipart.add_field(
68         &1,
69         key,
70         Jason.encode!(value),
71         headers: [{"content-type", "application/json"}]
72       )
73     )
74   end
75
76   def add_param(request, :file, name, path) do
77     request
78     |> Map.put(:body, Multipart.new())
79     |> Map.update!(:body, &Multipart.add_file(&1, path, name: name))
80   end
81
82   def add_param(request, :form, name, value) do
83     Map.update(request, :body, %{name => value}, &Map.put(&1, name, value))
84   end
85
86   def add_param(request, location, key, value) do
87     Map.update(request, location, [{key, value}], &(&1 ++ [{key, value}]))
88   end
89
90   def convert_to_keyword(request) do
91     request
92     |> Map.from_struct()
93     |> Enum.into([])
94   end
95 end