defmodule GitGudWeb.AvatarController do
@moduledoc """
Serves avatars for users, organizations and repositories.
GET /u/:handle/avatar
GET /orgs/:handle/avatar
GET /r/:owner/:name/avatar
Always an image. An owner with no upload gets the generated
identicon, which is what the profile page has always drawn — so a
caller never has to handle "no avatar", and an `<img>` never has a
broken state.
Unauthenticated on purpose. An avatar is decoration attached to a
handle that is already public, and requiring a session would break
every `<img>` in a federated context or an email.
"""
use GitGudWeb, :controller
alias GitGud.Avatars
alias GitGud.Repositories
# A year. Safe because the URL carries the content digest — a
# replaced avatar is a different URL, so nothing has to expire for
# the change to be seen.
@immutable_max_age 31_536_000
def user(conn, %{"handle" => handle}) do
case Repositories.resolve_namespace(handle) do
{:ok, owner} -> send_avatar(conn, owner)
:error -> send_resp(conn, 404, "")
end
end
def organization(conn, params), do: user(conn, params)
def repository(conn, %{"owner" => owner, "name" => name}) do
case Repositories.find_by_path(owner, name) do
nil -> send_resp(conn, 404, "")
repo -> send_avatar(conn, repo)
end
end
defp send_avatar(conn, owner) do
{:ok, content_type, body} = Avatars.render(owner)
conn
|> put_resp_content_type(content_type)
|> put_resp_header("cache-control", cache_control(conn))
# Belt and braces on a path that serves user-supplied bytes: the
# type is sniffed from the body on upload, but a browser that
# decides to sniff again shouldn't be able to reach a different
# conclusion.
|> put_resp_header("x-content-type-options", "nosniff")
|> send_resp(200, body)
end
# Only immutable when the request carried a version. A bare URL has
# to stay revalidatable, or a visitor who followed a link without one
# is stuck with a stale face for a year.
defp cache_control(conn) do
case conn.query_params do
%{"v" => v} when is_binary(v) and v != "" ->
"public, max-age=#{@immutable_max_age}, immutable"
_ ->
"public, max-age=300"
end
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
2.2 KiB · text
History
4b2ca85