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(Pleroma.Web.Plugs.InstanceStatic,
27 at: "/",
28 gzip: true,
29 cache_control_for_etags: @static_cache_control,
30 headers: %{
31 "cache-control" => @static_cache_control
32 }
33 )
34
35 # Careful! No `only` restriction here, as we don't know what frontends contain.
36 plug(Pleroma.Web.Plugs.FrontendStatic,
37 at: "/",
38 frontend_type: :primary,
39 gzip: true,
40 cache_control_for_etags: @static_cache_control,
41 headers: %{
42 "cache-control" => @static_cache_control
43 }
44 )
45
46 plug(Plug.Static.IndexHtml, at: "/pleroma/admin/")
47
48 plug(Pleroma.Web.Plugs.FrontendStatic,
49 at: "/pleroma/admin",
50 frontend_type: :admin,
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/fedife/")
59
60 plug(Pleroma.Web.Plugs.FrontendStatic,
61 at: "/pleroma/fedife",
62 frontend_type: :fedife,
63 gzip: true,
64 cache_control_for_etags: @static_cache_control,
65 headers: %{
66 "cache-control" => @static_cache_control
67 }
68 )
69
70
71 # Serve at "/" the static files from "priv/static" directory.
72 #
73 # You should set gzip to true if you are running phoenix.digest
74 # when deploying your static files in production.
75 plug(
76 Plug.Static,
77 at: "/",
78 from: :pleroma,
79 only: Pleroma.Constants.static_only_files(),
80 # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
81 gzip: true,
82 cache_control_for_etags: @static_cache_control,
83 headers: %{
84 "cache-control" => @static_cache_control
85 }
86 )
87
88 plug(Plug.Static,
89 at: "/pleroma/admin/",
90 from: {:pleroma, "priv/static/adminfe/"}
91 )
92
93 # Code reloading can be explicitly enabled under the
94 # :code_reloader configuration of your endpoint.
95 if code_reloading? do
96 plug(Phoenix.CodeReloader)
97 end
98
99 plug(Pleroma.Web.Plugs.TrailingFormatPlug)
100 plug(Plug.RequestId)
101 plug(Plug.Logger, log: :debug)
102
103 plug(Plug.Parsers,
104 parsers: [
105 :urlencoded,
106 {:multipart, length: {Config, :get, [[:instance, :upload_limit]]}},
107 :json
108 ],
109 pass: ["*/*"],
110 json_decoder: Jason,
111 length: Config.get([:instance, :upload_limit]),
112 body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []}
113 )
114
115 plug(Plug.MethodOverride)
116 plug(Plug.Head)
117
118 secure_cookies = Config.get([__MODULE__, :secure_cookie_flag])
119
120 cookie_name =
121 if secure_cookies,
122 do: "__Host-pleroma_key",
123 else: "pleroma_key"
124
125 extra =
126 Config.get([__MODULE__, :extra_cookie_attrs])
127 |> Enum.join(";")
128
129 # The session will be stored in the cookie and signed,
130 # this means its contents can be read but not tampered with.
131 # Set :encryption_salt if you would also like to encrypt it.
132 plug(
133 Plug.Session,
134 store: :cookie,
135 key: cookie_name,
136 signing_salt: Config.get([__MODULE__, :signing_salt], "CqaoopA2"),
137 http_only: true,
138 secure: secure_cookies,
139 extra: extra
140 )
141
142 plug(Pleroma.Web.Plugs.RemoteIp)
143
144 defmodule Instrumenter do
145 use Prometheus.PhoenixInstrumenter
146 end
147
148 defmodule PipelineInstrumenter do
149 use Prometheus.PlugPipelineInstrumenter
150 end
151
152 defmodule MetricsExporter do
153 use Prometheus.PlugExporter
154 end
155
156 defmodule MetricsExporterCaller do
157 @behaviour Plug
158
159 def init(opts), do: opts
160
161 def call(conn, opts) do
162 prometheus_config = Application.get_env(:prometheus, MetricsExporter, [])
163 ip_whitelist = List.wrap(prometheus_config[:ip_whitelist])
164
165 cond do
166 !prometheus_config[:enabled] ->
167 conn
168
169 ip_whitelist != [] and
170 !Enum.find(ip_whitelist, fn ip ->
171 Pleroma.Helpers.InetHelper.parse_address(ip) == {:ok, conn.remote_ip}
172 end) ->
173 conn
174
175 true ->
176 MetricsExporter.call(conn, opts)
177 end
178 end
179 end
180
181 plug(PipelineInstrumenter)
182
183 plug(MetricsExporterCaller)
184
185 plug(Pleroma.Web.Router)
186
187 @doc """
188 Dynamically loads configuration from the system environment
189 on startup.
190
191 It receives the endpoint configuration from the config files
192 and must return the updated configuration.
193 """
194 def load_from_system_env(config) do
195 port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
196 {:ok, Keyword.put(config, :http, [:inet6, port: port])}
197 end
198
199 def websocket_url do
200 String.replace_leading(url(), "http", "ws")
201 end
202 end