From 848b3f5d5b6e004c51e18a4adb04d721fb89ea5c Mon Sep 17 00:00:00 2001 From: Yonle Date: Mon, 23 Feb 2026 20:57:11 +0700 Subject: [PATCH 01/13] reverse_proxy,endpoint,uploaded_media: add immutable cache-control flag --- lib/pleroma/reverse_proxy.ex | 2 +- lib/pleroma/web/endpoint.ex | 2 +- lib/pleroma/web/plugs/uploaded_media.ex | 2 +- test/pleroma/reverse_proxy_test.exs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/reverse_proxy.ex b/lib/pleroma/reverse_proxy.ex index bb55a4984..c7ee47c6e 100644 --- a/lib/pleroma/reverse_proxy.ex +++ b/lib/pleroma/reverse_proxy.ex @@ -12,7 +12,7 @@ defmodule Pleroma.ReverseProxy do @keep_resp_headers @resp_cache_headers ++ ~w(content-length content-type content-disposition content-encoding) ++ ~w(content-range accept-ranges vary) - @default_cache_control_header "public, max-age=1209600" + @default_cache_control_header "public, max-age=1209600, immutable" @valid_resp_codes [200, 206, 304] @max_read_duration :timer.seconds(30) @max_body_length :infinity diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index bab3c9fd0..13c655ee2 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -46,7 +46,7 @@ defmodule Pleroma.Web.Endpoint do plug(Pleroma.Web.Plugs.HTTPSecurityPlug) plug(Pleroma.Web.Plugs.UploadedMedia) - @static_cache_control "public, max-age=1209600" + @static_cache_control "public, max-age=1209600, immutable" @static_cache_disabled "public, no-cache" # InstanceStatic needs to be before Plug.Static to be able to override shipped-static files diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex index abacf965b..5a3ea12aa 100644 --- a/lib/pleroma/web/plugs/uploaded_media.ex +++ b/lib/pleroma/web/plugs/uploaded_media.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do # no slashes @path "media" - @default_cache_control_header "public, max-age=1209600" + @default_cache_control_header "public, max-age=1209600, immutable" def init(_opts) do static_plug_opts = diff --git a/test/pleroma/reverse_proxy_test.exs b/test/pleroma/reverse_proxy_test.exs index 8dbe9c6bf..ec4470379 100644 --- a/test/pleroma/reverse_proxy_test.exs +++ b/test/pleroma/reverse_proxy_test.exs @@ -294,7 +294,7 @@ defmodule Pleroma.ReverseProxyTest do |> expect(:stream_body, fn _ -> :done end) conn = ReverseProxy.call(conn, "/cache") - assert {"cache-control", "public, max-age=1209600"} in conn.resp_headers + assert {"cache-control", "public, max-age=1209600, immutable"} in conn.resp_headers end end From 970e0f90441ff092fd6ee11ed0a87a06f4269373 Mon Sep 17 00:00:00 2001 From: Yonle Date: Mon, 2 Mar 2026 23:48:59 +0700 Subject: [PATCH 02/13] endpoint: set cache control for favicon.png Signed-off-by: Yonle --- lib/pleroma/web/endpoint.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 13c655ee2..f7c58f459 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -56,7 +56,7 @@ defmodule Pleroma.Web.Endpoint do Pleroma.Web.Plugs.InstanceStatic, at: "/", from: :pleroma, - only: ["emoji", "images"], + only: ["emoji", "images", "favicon.png"], gzip: true, cache_control_for_etags: @static_cache_control, headers: %{ From 8abd25950a483efcfa42ba113086dd6cc5730ebf Mon Sep 17 00:00:00 2001 From: Yonle Date: Wed, 4 Mar 2026 02:54:47 +0700 Subject: [PATCH 03/13] endpoint: use favicon plug --- lib/pleroma/web/endpoint.ex | 12 +++++- lib/pleroma/web/plugs/favicon.ex | 73 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 lib/pleroma/web/plugs/favicon.ex diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index f7c58f459..e769b11b1 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -48,6 +48,7 @@ defmodule Pleroma.Web.Endpoint do @static_cache_control "public, max-age=1209600, immutable" @static_cache_disabled "public, no-cache" + @favicon_cache_control "public, max=age=86400, immutable" # cache for a day # InstanceStatic needs to be before Plug.Static to be able to override shipped-static files # If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well @@ -56,7 +57,7 @@ defmodule Pleroma.Web.Endpoint do Pleroma.Web.Plugs.InstanceStatic, at: "/", from: :pleroma, - only: ["emoji", "images", "favicon.png"], + only: ["emoji", "images"], gzip: true, cache_control_for_etags: @static_cache_control, headers: %{ @@ -73,6 +74,15 @@ defmodule Pleroma.Web.Endpoint do } ) + plug(Pleroma.Web.Plugs.Favicon, + at: "/", + only: ["favicon.png"], + cache_control_for_etags: @favicon_cache_control, + headers: %{ + "cache-control" => @favicon_cache_control + } + ) + plug(Pleroma.Web.Plugs.FrontendStatic, at: "/", frontend_type: :primary, diff --git a/lib/pleroma/web/plugs/favicon.ex b/lib/pleroma/web/plugs/favicon.ex new file mode 100644 index 000000000..ad105c59a --- /dev/null +++ b/lib/pleroma/web/plugs/favicon.ex @@ -0,0 +1,73 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2026 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.Favicon do + @behaviour Plug + + @moduledoc """ + Serves favicon.png directly from the instance static directory, + bypassing the frontend-specific logic. + """ + + alias Pleroma.Web.Plugs.FrontendStatic + import Plug.Conn, only: [put_resp_header: 3] + + def init(opts) do + opts + |> Keyword.put(:from, "__unconfigured_favicon_static_plug") + |> Plug.Static.init() + end + + def call(conn, opts) do + if favicon_route?(conn.path_info) do + case find_favicon_dir(conn) do + {:ok, dir} -> + call_static(conn, opts, dir) + |> Plug.Conn.halt() + + :error -> + conn # Let the request keep going to a 404 + end + else + conn + end + end + + defp find_favicon_dir(conn) do + instance_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static") + instance_path = Path.join(instance_dir, "favicon.png") + + frontend_type = FrontendStatic.preferred_or_fallback(conn, :primary) + frontend_dir = FrontendStatic.file_path("", frontend_type) + frontend_path = if frontend_dir, do: Path.join(frontend_dir, "favicon.png"), else: nil + + 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} + frontend_path && File.exists?(frontend_path) -> {:ok, frontend_dir} + File.exists?(priv_path) -> {:ok, priv_dir} + true -> :error + end + end + + defp favicon_route?(["favicon.png"]), do: true + defp favicon_route?(_), do: false + + 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 From 4bc0b26abed50ca04041297f1f66467a8d812359 Mon Sep 17 00:00:00 2001 From: Yonle Date: Wed, 4 Mar 2026 02:57:53 +0700 Subject: [PATCH 04/13] changelog.d: add cache-control-immutable --- changelog.d/cache-control-immutable.add | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/cache-control-immutable.add diff --git a/changelog.d/cache-control-immutable.add b/changelog.d/cache-control-immutable.add new file mode 100644 index 000000000..516db67bf --- /dev/null +++ b/changelog.d/cache-control-immutable.add @@ -0,0 +1 @@ +Add immutable tag on cache-control header for several endpoints that's serving the same exact things. \ No newline at end of file From 0879dd39505bb9f577bd371a04f49b9beb2123ae Mon Sep 17 00:00:00 2001 From: Yonle Date: Wed, 4 Mar 2026 03:13:55 +0700 Subject: [PATCH 05/13] endpoint: reorder: handle favicon plug first --- lib/pleroma/web/endpoint.ex | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index e769b11b1..2bf64a1fd 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -65,15 +65,6 @@ defmodule Pleroma.Web.Endpoint do } ) - plug(Pleroma.Web.Plugs.InstanceStatic, - at: "/", - gzip: true, - cache_control_for_etags: @static_cache_disabled, - headers: %{ - "cache-control" => @static_cache_disabled - } - ) - plug(Pleroma.Web.Plugs.Favicon, at: "/", only: ["favicon.png"], @@ -83,6 +74,15 @@ defmodule Pleroma.Web.Endpoint do } ) + plug(Pleroma.Web.Plugs.InstanceStatic, + at: "/", + gzip: true, + cache_control_for_etags: @static_cache_disabled, + headers: %{ + "cache-control" => @static_cache_disabled + } + ) + plug(Pleroma.Web.Plugs.FrontendStatic, at: "/", frontend_type: :primary, From 96f252023e31549d934b42c098d6e62192f9f8d0 Mon Sep 17 00:00:00 2001 From: Yonle Date: Wed, 4 Mar 2026 22:49:54 +0700 Subject: [PATCH 06/13] constants: remove favicon.png from static_only_files --- lib/pleroma/constants.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index f78b84099..178dd6094 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -29,7 +29,7 @@ defmodule Pleroma.Constants do const(static_only_files, do: - ~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css) + ~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js schemas doc embed.js embed.css) ) const(status_updatable_fields, From 89751296803ba60354c16335f3422421710ddb00 Mon Sep 17 00:00:00 2001 From: Yonle Date: Thu, 5 Mar 2026 02:07:39 +0700 Subject: [PATCH 07/13] webplug(favicon): remove check on url path. --- lib/pleroma/web/plugs/favicon.ex | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/pleroma/web/plugs/favicon.ex b/lib/pleroma/web/plugs/favicon.ex index ad105c59a..32ef86cf8 100644 --- a/lib/pleroma/web/plugs/favicon.ex +++ b/lib/pleroma/web/plugs/favicon.ex @@ -20,17 +20,12 @@ defmodule Pleroma.Web.Plugs.Favicon do end def call(conn, opts) do - if favicon_route?(conn.path_info) do - case find_favicon_dir(conn) do - {:ok, dir} -> - call_static(conn, opts, dir) - |> Plug.Conn.halt() + case find_favicon_dir(conn) do + {:ok, dir} -> + call_static(conn, opts, dir) - :error -> - conn # Let the request keep going to a 404 - end - else - conn + :error -> + conn # Let the request keep going to a 404 end end @@ -53,9 +48,6 @@ defmodule Pleroma.Web.Plugs.Favicon do end end - defp favicon_route?(["favicon.png"]), do: true - defp favicon_route?(_), do: false - defp call_static(conn, opts, from) do opts = opts From d03ae43ee07a8d6467fe8b608ba69f2166a740e3 Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 10:28:09 +0100 Subject: [PATCH 08/13] Favicon Plug: Simplify and pass when not requesting favicon --- lib/pleroma/web/plugs/favicon.ex | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/pleroma/web/plugs/favicon.ex b/lib/pleroma/web/plugs/favicon.ex index 32ef86cf8..6564d2e00 100644 --- a/lib/pleroma/web/plugs/favicon.ex +++ b/lib/pleroma/web/plugs/favicon.ex @@ -10,7 +10,6 @@ defmodule Pleroma.Web.Plugs.Favicon do bypassing the frontend-specific logic. """ - alias Pleroma.Web.Plugs.FrontendStatic import Plug.Conn, only: [put_resp_header: 3] def init(opts) do @@ -19,8 +18,8 @@ defmodule Pleroma.Web.Plugs.Favicon do |> Plug.Static.init() end - def call(conn, opts) do - case find_favicon_dir(conn) do + def call(%{request_path: "/favicon.png"} = conn, opts) do + case find_favicon_dir() do {:ok, dir} -> call_static(conn, opts, dir) @@ -29,20 +28,19 @@ defmodule Pleroma.Web.Plugs.Favicon do end end - defp find_favicon_dir(conn) do + 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") - frontend_type = FrontendStatic.preferred_or_fallback(conn, :primary) - frontend_dir = FrontendStatic.file_path("", frontend_type) - frontend_path = if frontend_dir, do: Path.join(frontend_dir, "favicon.png"), else: nil - 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} - frontend_path && File.exists?(frontend_path) -> {:ok, frontend_dir} File.exists?(priv_path) -> {:ok, priv_dir} true -> :error end From 2388964b141bb963d1ab37ccdd00985140a2c6aa Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 11:37:02 +0100 Subject: [PATCH 09/13] Favicon Plug: Add tests --- test/pleroma/web/plugs/favicon_plug_test.exs | 69 ++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 test/pleroma/web/plugs/favicon_plug_test.exs diff --git a/test/pleroma/web/plugs/favicon_plug_test.exs b/test/pleroma/web/plugs/favicon_plug_test.exs new file mode 100644 index 000000000..36650e7bf --- /dev/null +++ b/test/pleroma/web/plugs/favicon_plug_test.exs @@ -0,0 +1,69 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2026 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.FaviconPlugTest do + use Pleroma.Web.ConnCase + + # import Mox + + # alias Pleroma.UnstubbedConfigMock, as: ConfigMock + + @dir "test/tmp/favicon_static" + + describe "default favicon" do + test "returns favicon", %{conn: conn} do + conn = get(conn, "/favicon.png") + etag = get_resp_header(conn, "etag") + + # etag changes when serving a different file + assert etag == ["\"72487CE\""] + assert response_content_type(conn, :png) + end + + test "returns correct cache-control", %{conn: conn} do + cache = + conn + |> get("/favicon.png") + |> get_resp_header("cache-control") + + 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") + + # 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) + end + + test "returns favicon", %{conn: conn} do + conn = get(conn, "/favicon.png") + etag = get_resp_header(conn, "etag") + + assert etag == ["\"215A3A4\""] + assert response_content_type(conn, :png) + end + + test "returns correct cache-control", %{conn: conn} do + cache = + conn + |> get("/favicon.png") + |> get_resp_header("cache-control") + + assert cache == ["public, max=age=86400, immutable"] + end + end +end From 662c9f36ac597c7f0bfbcdec8c12f2dfb87b8df0 Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 11:43:55 +0100 Subject: [PATCH 10/13] Favicon Plug: Update moduledoc and rename to adhere to convention --- lib/pleroma/web/endpoint.ex | 2 +- lib/pleroma/web/plugs/{favicon.ex => favicon_plug.ex} | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename lib/pleroma/web/plugs/{favicon.ex => favicon_plug.ex} (86%) diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 2bf64a1fd..81a9d3a09 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -65,7 +65,7 @@ defmodule Pleroma.Web.Endpoint do } ) - plug(Pleroma.Web.Plugs.Favicon, + plug(Pleroma.Web.Plugs.FaviconPlug, at: "/", only: ["favicon.png"], cache_control_for_etags: @favicon_cache_control, diff --git a/lib/pleroma/web/plugs/favicon.ex b/lib/pleroma/web/plugs/favicon_plug.ex similarity index 86% rename from lib/pleroma/web/plugs/favicon.ex rename to lib/pleroma/web/plugs/favicon_plug.ex index 6564d2e00..d50a03d83 100644 --- a/lib/pleroma/web/plugs/favicon.ex +++ b/lib/pleroma/web/plugs/favicon_plug.ex @@ -2,12 +2,13 @@ # Copyright © 2017-2026 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.Web.Plugs.Favicon do +defmodule Pleroma.Web.Plugs.FaviconPlug do @behaviour Plug @moduledoc """ - Serves favicon.png directly from the instance static directory, - bypassing the frontend-specific logic. + 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] From d0db1f00c3d52cab72de6db300bb99d58b1f289a Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 11:55:02 +0100 Subject: [PATCH 11/13] Favicon Plug: assert HTTP 200 status in tests --- test/pleroma/web/plugs/favicon_plug_test.exs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/pleroma/web/plugs/favicon_plug_test.exs b/test/pleroma/web/plugs/favicon_plug_test.exs index 36650e7bf..87d955ccc 100644 --- a/test/pleroma/web/plugs/favicon_plug_test.exs +++ b/test/pleroma/web/plugs/favicon_plug_test.exs @@ -17,16 +17,16 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do etag = get_resp_header(conn, "etag") # etag changes when serving a different file + assert conn.status == 200 assert etag == ["\"72487CE\""] assert response_content_type(conn, :png) end test "returns correct cache-control", %{conn: conn} do - cache = - conn - |> get("/favicon.png") - |> get_resp_header("cache-control") + 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 @@ -53,16 +53,16 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do conn = get(conn, "/favicon.png") etag = get_resp_header(conn, "etag") + assert conn.status == 200 assert etag == ["\"215A3A4\""] assert response_content_type(conn, :png) end test "returns correct cache-control", %{conn: conn} do - cache = - conn - |> get("/favicon.png") - |> get_resp_header("cache-control") + 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 From 5f321b0b5b10d0a3324b588b8f9af01878ecac04 Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 12:49:20 +0100 Subject: [PATCH 12/13] Favicon Plug: Halt Plug pipeline when favicon not found --- lib/pleroma/web/plugs/favicon_plug.ex | 12 ++++++-- test/pleroma/web/plugs/favicon_plug_test.exs | 30 ++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) 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 @@ -11,7 +11,9 @@ defmodule Pleroma.Web.Plugs.FaviconPlug do 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 @@ -25,7 +27,12 @@ defmodule Pleroma.Web.Plugs.FaviconPlug do 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 @@ -54,7 +61,6 @@ defmodule Pleroma.Web.Plugs.FaviconPlug do |> Map.put(:content_types, false) conn = set_content_type(conn) - Plug.Static.call(conn, opts) 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 @@ -5,20 +5,21 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do use Pleroma.Web.ConnCase - # import Mox - - # alias Pleroma.UnstubbedConfigMock, as: ConfigMock - @dir "test/tmp/favicon_static" + setup do + Pleroma.Backports.mkdir_p!(@dir) + + 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 @@ -33,28 +34,21 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do 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 From 3760480813745c0f2d0b2fe1a8642400308e2be2 Mon Sep 17 00:00:00 2001 From: Phantasm Date: Thu, 5 Mar 2026 11:48:37 +0100 Subject: [PATCH 13/13] lint --- lib/pleroma/web/plugs/favicon_plug.ex | 3 ++- test/pleroma/web/plugs/favicon_plug_test.exs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/pleroma/web/plugs/favicon_plug.ex b/lib/pleroma/web/plugs/favicon_plug.ex index 1f8b891a1..e2e1f1adb 100644 --- a/lib/pleroma/web/plugs/favicon_plug.ex +++ b/lib/pleroma/web/plugs/favicon_plug.ex @@ -30,6 +30,7 @@ defmodule Pleroma.Web.Plugs.FaviconPlug do # 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() @@ -40,7 +41,7 @@ defmodule Pleroma.Web.Plugs.FaviconPlug do conn end - defp find_favicon_dir() do + defp find_favicon_dir do instance_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static") instance_path = Path.join(instance_dir, "favicon.png") diff --git a/test/pleroma/web/plugs/favicon_plug_test.exs b/test/pleroma/web/plugs/favicon_plug_test.exs index 62926e041..520501250 100644 --- a/test/pleroma/web/plugs/favicon_plug_test.exs +++ b/test/pleroma/web/plugs/favicon_plug_test.exs @@ -8,9 +8,9 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do @dir "test/tmp/favicon_static" setup do - Pleroma.Backports.mkdir_p!(@dir) + Pleroma.Backports.mkdir_p!(@dir) - on_exit(fn -> File.rm_rf!(@dir) end) + on_exit(fn -> File.rm_rf!(@dir) end) end describe "default favicon" do @@ -48,12 +48,12 @@ defmodule Pleroma.Web.Plugs.FaviconPlugTest do body_size = byte_size(conn.resp_body) assert conn.status == 200 - assert body_size == 104426 + assert body_size == 104_426 assert response_content_type(conn, :png) end test "returns correct cache-control", %{conn: conn} do - conn = get(conn ,"/favicon.png") + conn = get(conn, "/favicon.png") cache = get_resp_header(conn, "cache-control") assert conn.status == 200