Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
[akkoma] / lib / pleroma / web / endpoint.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.Endpoint do
6 use Phoenix.Endpoint, otp_app: :pleroma
7
8 require Pleroma.Constants
9
10 alias Pleroma.Config
11
12 socket("/socket", Pleroma.Web.UserSocket)
13
14 plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint])
15
16 plug(Pleroma.Web.Plugs.SetLocalePlug)
17 plug(CORSPlug)
18 plug(Pleroma.Web.Plugs.HTTPSecurityPlug)
19 plug(Pleroma.Web.Plugs.UploadedMedia)
20
21 @static_cache_control "public, no-cache"
22
23 # InstanceStatic needs to be before Plug.Static to be able to override shipped-static files
24 # If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well
25 # Cache-control headers are duplicated in case we turn off etags in the future
26 plug(
27 Pleroma.Web.Plugs.InstanceStatic,
28 at: "/",
29 from: :pleroma,
30 only: ["emoji", "images"],
31 gzip: true,
32 cache_control_for_etags: "public, max-age=1209600",
33 headers: %{
34 "cache-control" => "public, max-age=1209600"
35 }
36 )
37
38 plug(Pleroma.Web.Plugs.InstanceStatic,
39 at: "/",
40 gzip: true,
41 cache_control_for_etags: @static_cache_control,
42 headers: %{
43 "cache-control" => @static_cache_control
44 }
45 )
46
47 # Careful! No `only` restriction here, as we don't know what frontends contain.
48 plug(Pleroma.Web.Plugs.FrontendStatic,
49 at: "/",
50 frontend_type: :primary,
51 gzip: true,
52 cache_control_for_etags: @static_cache_control,
53 headers: %{
54 "cache-control" => @static_cache_control
55 }
56 )
57
58 plug(Plug.Static.IndexHtml, at: "/pleroma/admin/")
59
60 plug(Pleroma.Web.Plugs.FrontendStatic,
61 at: "/pleroma/admin",
62 frontend_type: :admin,
63 gzip: true,
64 cache_control_for_etags: @static_cache_control,
65 headers: %{
66 "cache-control" => @static_cache_control
67 }
68 )
69
70 plug(Plug.Static.IndexHtml, at: "/pleroma/fedife/")
71
72 plug(Pleroma.Web.Plugs.FrontendStatic,
73 at: "/pleroma/fedife",
74 frontend_type: :fedife,
75 gzip: true,
76 cache_control_for_etags: @static_cache_control,
77 headers: %{
78 "cache-control" => @static_cache_control
79 }
80 )
81
82
83 # Serve at "/" the static files from "priv/static" directory.
84 #
85 # You should set gzip to true if you are running phoenix.digest
86 # when deploying your static files in production.
87 plug(
88 Plug.Static,
89 at: "/",
90 from: :pleroma,
91 only: Pleroma.Constants.static_only_files(),
92 # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
93 gzip: true,
94 cache_control_for_etags: @static_cache_control,
95 headers: %{
96 "cache-control" => @static_cache_control
97 }
98 )
99
100 plug(Plug.Static,
101 at: "/pleroma/admin/",
102 from: {:pleroma, "priv/static/adminfe/"}
103 )
104
105 # Code reloading can be explicitly enabled under the
106 # :code_reloader configuration of your endpoint.
107 if code_reloading? do
108 plug(Phoenix.CodeReloader)
109 end
110
111 plug(Pleroma.Web.Plugs.TrailingFormatPlug)
112 plug(Plug.RequestId)
113 plug(Plug.Logger, log: :debug)
114
115 plug(Plug.Parsers,
116 parsers: [
117 :urlencoded,
118 {:multipart, length: {Config, :get, [[:instance, :upload_limit]]}},
119 :json
120 ],
121 pass: ["*/*"],
122 json_decoder: Jason,
123 length: Config.get([:instance, :upload_limit]),
124 body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []}
125 )
126
127 plug(Plug.MethodOverride)
128 plug(Plug.Head)
129
130 secure_cookies = Config.get([__MODULE__, :secure_cookie_flag])
131
132 cookie_name =
133 if secure_cookies,
134 do: "__Host-pleroma_key",
135 else: "pleroma_key"
136
137 extra =
138 Config.get([__MODULE__, :extra_cookie_attrs])
139 |> Enum.join(";")
140
141 # The session will be stored in the cookie and signed,
142 # this means its contents can be read but not tampered with.
143 # Set :encryption_salt if you would also like to encrypt it.
144 plug(
145 Plug.Session,
146 store: :cookie,
147 key: cookie_name,
148 signing_salt: Config.get([__MODULE__, :signing_salt], "CqaoopA2"),
149 http_only: true,
150 secure: secure_cookies,
151 extra: extra
152 )
153
154 plug(Pleroma.Web.Plugs.RemoteIp)
155
156 defmodule Instrumenter do
157 use Prometheus.PhoenixInstrumenter
158 end
159
160 defmodule PipelineInstrumenter do
161 use Prometheus.PlugPipelineInstrumenter
162 end
163
164 defmodule MetricsExporter do
165 use Prometheus.PlugExporter
166 end
167
168 defmodule MetricsExporterCaller do
169 @behaviour Plug
170
171 def init(opts), do: opts
172
173 def call(conn, opts) do
174 prometheus_config = Application.get_env(:prometheus, MetricsExporter, [])
175 ip_whitelist = List.wrap(prometheus_config[:ip_whitelist])
176
177 cond do
178 !prometheus_config[:enabled] ->
179 conn
180
181 ip_whitelist != [] and
182 !Enum.find(ip_whitelist, fn ip ->
183 Pleroma.Helpers.InetHelper.parse_address(ip) == {:ok, conn.remote_ip}
184 end) ->
185 conn
186
187 true ->
188 MetricsExporter.call(conn, opts)
189 end
190 end
191 end
192
193 plug(PipelineInstrumenter)
194
195 plug(MetricsExporterCaller)
196
197 plug(Pleroma.Web.Router)
198
199 @doc """
200 Dynamically loads configuration from the system environment
201 on startup.
202
203 It receives the endpoint configuration from the config files
204 and must return the updated configuration.
205 """
206 def load_from_system_env(config) do
207 port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
208 {:ok, Keyword.put(config, :http, [:inet6, port: port])}
209 end
210
211 def websocket_url do
212 String.replace_leading(url(), "http", "ws")
213 end
214 end