| defmodule PlausibleWeb.AvatarController do |
| @moduledoc """ |
| This module proxies requests to BASE_URL/avatar/:hash to www.gravatar.com/avatar/:hash. |
| |
| The purpose is to make use of Gravatar's convenient avatar service without exposing information |
| that could be used for tracking the Plausible user. Compared to requesting the Gravatar directly |
| from the browser, this proxy module protects the Plausible user from disclosing to Gravatar: |
| 1. The client IP address |
| 2. User-Agent |
| 3. Referer header which can be used to track which site the user is visiting (i.e. plausible.io or self-hosted URL) |
| |
| The downside is the added latency from the request having to go through the Plausible server, rather than contacting the |
| local CDN server operated by Gravatar's service. |
| """ |
| use PlausibleWeb, :controller |
| alias Plausible.HTTPClient |
|
|
| @gravatar_base_url "https://www.gravatar.com" |
| def avatar(conn, params) do |
| url = Path.join(@gravatar_base_url, ["avatar/", params["hash"]]) <> "?s=150&d=identicon" |
|
|
| case HTTPClient.impl().get(url) do |
| {:ok, %Finch.Response{status: 200, body: body, headers: headers}} -> |
| conn |
| |> forward_headers(headers) |
| |> send_resp(200, body) |
|
|
| {:error, _} -> |
| send_resp(conn, 400, "") |
| end |
| end |
|
|
| @forwarded_headers ["content-type", "cache-control", "expires"] |
| defp forward_headers(%Plug.Conn{} = conn, headers) do |
| headers_to_forward = Enum.filter(headers, fn {k, _} -> k in @forwarded_headers end) |
| %Plug.Conn{conn | resp_headers: headers_to_forward} |
| end |
| end |
|
|