Skip to content
Snippets Groups Projects
Verified Commit 1cb5cbdc authored by href's avatar href
Browse files

Improve error handling, add configuration

parent e28c110e
No related branches found
No related tags found
No related merge requests found
......@@ -47,6 +47,11 @@ config :pleroma, :instance,
limit: 5000,
registrations_open: true
config :pleroma, :media_proxy,
enabled: false,
redirect_on_failure: true
#base_url: "https://cache.pleroma.social"
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs"
......@@ -2,19 +2,27 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
use Pleroma.Web, :controller
require Logger
@cache_control %{
default: "public, max-age=1209600",
error: "public, must-revalidate, max-age=160",
}
def remote(conn, %{"sig" => sig, "url" => url}) do
{:ok, url} = Pleroma.Web.MediaProxy.decode_url(sig, url)
url = url |> URI.encode()
case proxy_request(url) do
{:ok, content_type, body} ->
conn
|> put_resp_content_type(content_type)
|> set_cache_header(:default)
|> send_resp(200, body)
other ->
conn
|> set_cache_header(:error)
|> redirect(external: url)
config = Application.get_env(:pleroma, :media_proxy, [])
with \
true <- Keyword.get(config, :enabled, false),
{:ok, url} <- Pleroma.Web.MediaProxy.decode_url(sig, url),
url = URI.encode(url),
{:ok, content_type, body} <- proxy_request(url)
do
conn
|> put_resp_content_type(content_type)
|> set_cache_header(:default)
|> send_resp(200, body)
else
false -> send_error(conn, 404)
{:error, :invalid_signature} -> send_error(conn, 403)
{:error, {:http, _, url}} -> redirect_or_error(conn, url, Keyword.get(config, :redirect_on_failure, true))
end
end
......@@ -28,21 +36,24 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
{:ok, headers["Content-Type"], body}
{:ok, status, _, _} ->
Logger.warn "MediaProxy: request failed, status #{status}, link: #{link}"
{:error, :bad_status}
{:error, {:http, :bad_status, link}}
{:error, error} ->
Logger.warn "MediaProxy: request failed, error #{inspect error}, link: #{link}"
{:error, error}
{:error, {:http, error, link}}
end
end
@cache_control %{
default: "public, max-age=1209600",
error: "public, must-revalidate, max-age=160",
}
defp set_cache_header(conn, key) do
Plug.Conn.put_resp_header(conn, "cache-control", @cache_control[key])
end
defp redirect_or_error(conn, url, true), do: redirect(conn, external: url)
defp redirect_or_error(conn, url, _), do: send_error(conn, 502, "Media proxy error: " <> url)
defp set_cache_header(conn, true), do: set_cache_header(conn, :default)
defp set_cache_header(conn, false), do: set_cache_header(conn, :error)
defp set_cache_header(conn, key) when is_atom(key), do: set_cache_header(conn, @cache_control[key])
defp set_cache_header(conn, value) when is_binary(value), do: Plug.Conn.put_resp_header(conn, "cache-control", value)
defp send_error(conn, code, body \\ "") do
conn
|> set_cache_header(:error)
|> send_resp(code, body)
end
end
defmodule Pleroma.Web.MediaProxy do
@base64_opts [padding: false]
@base64_key Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
def url(nil), do: nil
def url(url) do
if String.starts_with?(url, Pleroma.Web.base_url) do
config = Application.get_env(:pleroma, :media_proxy, [])
if !Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url) do
url
else
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
base64 = Base.url_encode64(url, @base64_opts)
sig = :crypto.hmac(:sha, @base64_key, base64)
sig = :crypto.hmac(:sha, secret, base64)
sig64 = sig |> Base.url_encode64(@base64_opts)
cache_url("#{sig64}/#{base64}")
Keyword.get(config, :base_url, Pleroma.Web.base_url) <> "/proxy/#{sig64}/#{base64}"
end
end
def decode_url(sig, url) do
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
sig = Base.url_decode64!(sig, @base64_opts)
local_sig = :crypto.hmac(:sha, @base64_key, url)
local_sig = :crypto.hmac(:sha, secret, url)
if local_sig == sig do
{:ok, Base.url_decode64!(url, @base64_opts)}
else
......@@ -25,9 +27,4 @@ defmodule Pleroma.Web.MediaProxy do
end
end
defp cache_url(path) do
"/proxy/" <> path
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment