Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/plugs/favicon_plug.ex b/lib/pleroma/web/plugs/favicon_plug.ex
index d50a03d83..1f8b891a1 100644
--- a/lib/pleroma/web/plugs/favicon_plug.ex
+++ b/lib/pleroma/web/plugs/favicon_plug.ex
@@ -1,64 +1,70 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2026 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.FaviconPlug do
@behaviour Plug
@moduledoc """
This is a shim to call `Plug.Static` but with runtime `from` configuration for instance favicon.
Serves default or custom favicon.png with cacheable cache-control.
"""
- import Plug.Conn, only: [put_resp_header: 3]
+ import Plug.Conn, only: [put_resp_header: 3, send_resp: 3, halt: 1]
+
+ require Logger
def init(opts) do
opts
|> Keyword.put(:from, "__unconfigured_favicon_static_plug")
|> Plug.Static.init()
end
def call(%{request_path: "/favicon.png"} = conn, opts) do
case find_favicon_dir() do
{:ok, dir} ->
call_static(conn, opts, dir)
:error ->
- conn # Let the request keep going to a 404
+ # Favicon should always be available and this should never occur.
+ # If it does, halt the pipeline before having unintended side-effects.
+ Logger.error("No favicon.png found! Is the default favicon deleted?")
+ conn
+ |> send_resp(404, "Not found")
+ |> halt()
end
end
def call(conn, _) do
conn
end
defp find_favicon_dir() do
instance_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static")
instance_path = Path.join(instance_dir, "favicon.png")
priv_dir = Application.app_dir(:pleroma, "priv/static")
priv_path = Path.join(priv_dir, "favicon.png")
cond do
File.exists?(instance_path) -> {:ok, instance_dir}
File.exists?(priv_path) -> {:ok, priv_dir}
true -> :error
end
end
defp call_static(conn, opts, from) do
opts =
opts
|> Map.put(:from, from)
|> Map.put(:content_types, false)
conn = set_content_type(conn)
-
Plug.Static.call(conn, opts)
end
defp set_content_type(conn) do
put_resp_header(conn, "content-type", "image/png")
end
end
diff --git a/test/pleroma/web/plugs/favicon_plug_test.exs b/test/pleroma/web/plugs/favicon_plug_test.exs
index 87d955ccc..62926e041 100644
--- a/test/pleroma/web/plugs/favicon_plug_test.exs
+++ b/test/pleroma/web/plugs/favicon_plug_test.exs
@@ -1,69 +1,63 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2026 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.FaviconPlugTest do
use Pleroma.Web.ConnCase
- # import Mox
+ @dir "test/tmp/favicon_static"
- # alias Pleroma.UnstubbedConfigMock, as: ConfigMock
+ setup do
+ Pleroma.Backports.mkdir_p!(@dir)
- @dir "test/tmp/favicon_static"
+ on_exit(fn -> File.rm_rf!(@dir) end)
+ end
describe "default favicon" do
test "returns favicon", %{conn: conn} do
conn = get(conn, "/favicon.png")
- etag = get_resp_header(conn, "etag")
+ body_size = byte_size(conn.resp_body)
- # etag changes when serving a different file
assert conn.status == 200
- assert etag == ["\"72487CE\""]
+ assert body_size == 1583
assert response_content_type(conn, :png)
end
test "returns correct cache-control", %{conn: conn} do
conn = get(conn, "/favicon.png")
cache = get_resp_header(conn, "cache-control")
assert conn.status == 200
assert cache == ["public, max=age=86400, immutable"]
end
end
describe "custom favicon" do
setup do
- Pleroma.Backports.mkdir_p!(@dir)
favicon_path = Path.join(@dir, "favicon.png")
+ donor_image = "test/fixtures/image.png"
- # Favicon plug should always return image/png
- donor_image = "test/fixtures/image.gif"
- image_stat = File.stat!(donor_image)
-
- # Preserve stat since that's what etag is based on
File.cp!(donor_image, favicon_path)
- File.write_stat!(favicon_path, image_stat)
-
clear_config([:instance, :static_dir], @dir)
- on_exit( fn -> File.rm_rf!(@dir) end)
+ on_exit(fn -> File.rm!(favicon_path) end)
end
test "returns favicon", %{conn: conn} do
conn = get(conn, "/favicon.png")
- etag = get_resp_header(conn, "etag")
+ body_size = byte_size(conn.resp_body)
assert conn.status == 200
- assert etag == ["\"215A3A4\""]
+ assert body_size == 104426
assert response_content_type(conn, :png)
end
test "returns correct cache-control", %{conn: conn} do
conn = get(conn ,"/favicon.png")
cache = get_resp_header(conn, "cache-control")
assert conn.status == 200
assert cache == ["public, max=age=86400, immutable"]
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 31, 3:18 AM (16 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1800969
Default Alt Text
(4 KB)

Event Timeline