Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85804654
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
index f10dc3ce5..e5eb6896a 100644
--- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
@@ -1,70 +1,68 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
@moduledoc "Preloads any attachments in the MediaProxy cache by prefetching them"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
alias Pleroma.HTTP
alias Pleroma.Web.MediaProxy
require Logger
- @adapter_options [
- pool: :media,
- recv_timeout: 10_000
- ]
-
@impl true
def history_awareness, do: :auto
defp prefetch(url) do
# Fetching only proxiable resources
if MediaProxy.enabled?() and MediaProxy.url_proxiable?(url) do
# If preview proxy is enabled, it'll also hit media proxy (so we're caching both requests)
prefetch_url = MediaProxy.preview_url(url)
Logger.debug("Prefetching #{inspect(url)} as #{inspect(prefetch_url)}")
if Pleroma.Config.get(:env) == :test do
fetch(prefetch_url)
else
Task.start(fn -> fetch(prefetch_url) end)
end
end
end
- defp fetch(url), do: HTTP.get(url, [], @adapter_options)
+ defp fetch(url) do
+ http_client_opts = Pleroma.Config.get([:media_proxy, :proxy_opts, :http], pool: :media)
+ HTTP.get(url, [], http_client_opts)
+ end
defp preload(%{"object" => %{"attachment" => attachments}} = _message) do
Enum.each(attachments, fn
%{"url" => url} when is_list(url) ->
url
|> Enum.each(fn
%{"href" => href} ->
prefetch(href)
x ->
Logger.debug("Unhandled attachment URL object #{inspect(x)}")
end)
x ->
Logger.debug("Unhandled attachment #{inspect(x)}")
end)
end
@impl true
def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = message)
when type in ["Create", "Update"] and is_list(attachments) and length(attachments) > 0 do
preload(message)
{:ok, message}
end
@impl true
def filter(message), do: {:ok, message}
@impl true
def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/media_proxy/media_proxy_controller.ex b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
index c11484ecb..0b446e0a6 100644
--- a/lib/pleroma/web/media_proxy/media_proxy_controller.ex
+++ b/lib/pleroma/web/media_proxy/media_proxy_controller.ex
@@ -1,212 +1,213 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MediaProxy.MediaProxyController do
use Pleroma.Web, :controller
alias Pleroma.Config
alias Pleroma.Helpers.MediaHelper
alias Pleroma.Helpers.UriHelper
alias Pleroma.ReverseProxy
alias Pleroma.Web.MediaProxy
alias Plug.Conn
plug(:sandbox)
def remote(conn, %{"sig" => sig64, "url" => url64}) do
with {_, true} <- {:enabled, MediaProxy.enabled?()},
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
{_, false} <- {:in_banned_urls, MediaProxy.in_banned_urls(url)},
:ok <- MediaProxy.verify_request_path_and_url(conn, url) do
ReverseProxy.call(conn, url, media_proxy_opts())
else
{:enabled, false} ->
send_resp(conn, 404, Conn.Status.reason_phrase(404))
{:in_banned_urls, true} ->
send_resp(conn, 404, Conn.Status.reason_phrase(404))
{:error, :invalid_signature} ->
send_resp(conn, 403, Conn.Status.reason_phrase(403))
{:wrong_filename, filename} ->
redirect(conn, external: MediaProxy.build_url(sig64, url64, filename))
end
end
def preview(%Conn{} = conn, %{"sig" => sig64, "url" => url64}) do
with {_, true} <- {:enabled, MediaProxy.preview_enabled?()},
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
:ok <- MediaProxy.verify_request_path_and_url(conn, url) do
handle_preview(conn, url)
else
{:enabled, false} ->
send_resp(conn, 404, Conn.Status.reason_phrase(404))
{:error, :invalid_signature} ->
send_resp(conn, 403, Conn.Status.reason_phrase(403))
{:wrong_filename, filename} ->
redirect(conn, external: MediaProxy.build_preview_url(sig64, url64, filename))
end
end
defp handle_preview(conn, url) do
media_proxy_url = MediaProxy.url(url)
+ http_client_opts = Pleroma.Config.get([:media_proxy, :proxy_opts, :http], pool: :media)
with {:ok, %{status: status} = head_response} when status in 200..299 <-
- Pleroma.HTTP.request(:head, media_proxy_url, "", [], pool: :media) do
+ Pleroma.HTTP.request(:head, media_proxy_url, "", [], http_client_opts) do
content_type = Tesla.get_header(head_response, "content-type")
content_length = Tesla.get_header(head_response, "content-length")
content_length = content_length && String.to_integer(content_length)
static = conn.params["static"] in ["true", true]
cond do
static and content_type == "image/gif" ->
handle_jpeg_preview(conn, media_proxy_url)
static ->
drop_static_param_and_redirect(conn)
content_type == "image/gif" ->
redirect(conn, external: media_proxy_url)
min_content_length_for_preview() > 0 and content_length > 0 and
content_length < min_content_length_for_preview() ->
redirect(conn, external: media_proxy_url)
true ->
handle_preview(content_type, conn, media_proxy_url)
end
else
# If HEAD failed, redirecting to media proxy URI doesn't make much sense; returning an error
{_, %{status: status}} ->
send_resp(conn, :failed_dependency, "Can't fetch HTTP headers (HTTP #{status}).")
{:error, :recv_response_timeout} ->
send_resp(conn, :failed_dependency, "HEAD request timeout.")
_ ->
send_resp(conn, :failed_dependency, "Can't fetch HTTP headers.")
end
end
defp handle_preview("image/png" <> _ = _content_type, conn, media_proxy_url) do
handle_png_preview(conn, media_proxy_url)
end
defp handle_preview("image/" <> _ = _content_type, conn, media_proxy_url) do
handle_jpeg_preview(conn, media_proxy_url)
end
defp handle_preview("video/" <> _ = _content_type, conn, media_proxy_url) do
handle_video_preview(conn, media_proxy_url)
end
defp handle_preview(_unsupported_content_type, conn, media_proxy_url) do
fallback_on_preview_error(conn, media_proxy_url)
end
defp handle_png_preview(conn, media_proxy_url) do
quality = Config.get!([:media_preview_proxy, :image_quality])
{thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions()
with {:ok, thumbnail_binary} <-
MediaHelper.image_resize(
media_proxy_url,
%{
max_width: thumbnail_max_width,
max_height: thumbnail_max_height,
quality: quality,
format: "png"
}
) do
conn
|> put_preview_response_headers(["image/png", "preview.png"])
|> send_resp(200, thumbnail_binary)
else
_ ->
fallback_on_preview_error(conn, media_proxy_url)
end
end
defp handle_jpeg_preview(conn, media_proxy_url) do
quality = Config.get!([:media_preview_proxy, :image_quality])
{thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions()
with {:ok, thumbnail_binary} <-
MediaHelper.image_resize(
media_proxy_url,
%{max_width: thumbnail_max_width, max_height: thumbnail_max_height, quality: quality}
) do
conn
|> put_preview_response_headers()
|> send_resp(200, thumbnail_binary)
else
_ ->
fallback_on_preview_error(conn, media_proxy_url)
end
end
defp handle_video_preview(conn, media_proxy_url) do
with {:ok, thumbnail_binary} <-
MediaHelper.video_framegrab(media_proxy_url) do
conn
|> put_preview_response_headers()
|> send_resp(200, thumbnail_binary)
else
_ ->
fallback_on_preview_error(conn, media_proxy_url)
end
end
defp drop_static_param_and_redirect(conn) do
uri_without_static_param =
conn
|> current_url()
|> UriHelper.modify_uri_params(%{}, ["static"])
redirect(conn, external: uri_without_static_param)
end
defp fallback_on_preview_error(conn, media_proxy_url) do
redirect(conn, external: media_proxy_url)
end
defp put_preview_response_headers(
conn,
[content_type, filename] = _content_info \\ ["image/jpeg", "preview.jpg"]
) do
conn
|> put_resp_header("content-type", content_type)
|> put_resp_header("content-disposition", "inline; filename=\"#{filename}\"")
|> put_resp_header("cache-control", ReverseProxy.default_cache_control_header())
end
defp thumbnail_max_dimensions do
config = media_preview_proxy_config()
thumbnail_max_width = Keyword.fetch!(config, :thumbnail_max_width)
thumbnail_max_height = Keyword.fetch!(config, :thumbnail_max_height)
{thumbnail_max_width, thumbnail_max_height}
end
defp min_content_length_for_preview do
Keyword.get(media_preview_proxy_config(), :min_content_length, 0)
end
defp media_preview_proxy_config do
Config.get!([:media_preview_proxy])
end
defp media_proxy_opts do
Config.get([:media_proxy, :proxy_opts], [])
end
defp sandbox(conn, _params) do
conn
|> merge_resp_headers([{"content-security-policy", "sandbox;"}])
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 10, 12:43 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1785197
Default Alt Text
(9 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline
Log In to Comment