diff options
author | href <href@random.sh> | 2017-11-22 19:06:07 +0100 |
---|---|---|
committer | href <href@random.sh> | 2017-11-28 20:50:34 +0100 |
commit | 5f35fdcf5d7bc0dc6054eda06d565268f9e79b33 (patch) | |
tree | 9412d2167d50c8ae5f8a0a98ec2811b2a1bf07a3 /lib/pleroma/web/media_proxy | |
parent | 9d1c0ec18dcf407bbac14868f64e98e1ec499c34 (diff) | |
download | pleroma-5f35fdcf5d7bc0dc6054eda06d565268f9e79b33.tar.gz |
media proxy: good enough wip
Diffstat (limited to 'lib/pleroma/web/media_proxy')
-rw-r--r-- | lib/pleroma/web/media_proxy/controller.ex | 49 | ||||
-rw-r--r-- | lib/pleroma/web/media_proxy/media_proxy.ex | 33 |
2 files changed, 82 insertions, 0 deletions
diff --git a/lib/pleroma/web/media_proxy/controller.ex b/lib/pleroma/web/media_proxy/controller.ex new file mode 100644 index 000000000..84c6e9c8b --- /dev/null +++ b/lib/pleroma/web/media_proxy/controller.ex @@ -0,0 +1,49 @@ +defmodule Pleroma.Web.MediaProxy.MediaProxyController do + use Pleroma.Web, :controller + require Logger + + def remote(conn, %{"sig" => sig, "url" => url}) do + {:ok, url} = Pleroma.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) + end + end + + defp proxy_request(link) do + instance = ) + headers = [{"user-agent", "Pleroma/MediaProxy; #{Pleroma.Web.base_url()} <#{Application.get_env(:pleroma, :instance)[:email]}>"}] + options = [:insecure, {:follow_redirect, true}] + case :hackney.request(:get, link, headers, "", options) do + {:ok, 200, headers, client} -> + headers = Enum.into(headers, Map.new) + {:ok, body} = :hackney.body(client) + {:ok, headers["Content-Type"], body} + {:ok, status, _, _} -> + Logger.warn "MediaProxy: request failed, status #{status}, link: #{link}" + {:error, :bad_status} + {:error, error} -> + Logger.warn "MediaProxy: request failed, error #{inspect error}, link: #{link}" + {:error, error} + end + end + + @cache_control %{ + default: "public, max-age=1209600", + error: "public, must-revalidate, max-age=160", + } + + 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) + +end diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex new file mode 100644 index 000000000..9c1d71748 --- /dev/null +++ b/lib/pleroma/web/media_proxy/media_proxy.ex @@ -0,0 +1,33 @@ +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 + url + else + base64 = Base.url_encode64(url, @base64_opts) + sig = :crypto.hmac(:sha, @base64_key, base64) + sig64 = sig |> Base.url_encode64(@base64_opts) + cache_url("#{sig64}/#{base64}") + end + end + + def decode_url(sig, url) do + sig = Base.url_decode64!(sig, @base64_opts) + local_sig = :crypto.hmac(:sha, @base64_key, url) + if local_sig == sig do + {:ok, Base.url_decode64!(url, @base64_opts)} + else + {:error, :invalid_signature} + end + end + + defp cache_url(path) do + "/proxy/" <> path + end + + +end |