fix(cloudflare): cache the gamedata tree at the edge with respect_origin
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 32s
CI / tests-unit (push) Successful in 1m44s
CI / tests-integration (push) Successful in 1m44s
CI / tests-ui (push) Successful in 2m31s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m16s

Icons are plain .png, a cacheable extension by default, so the zone's
"Browser Cache TTL = 1 year" pinned them to max-age=31536000 regardless of
the 300/3600/604800 that nginx sends per class. Extend the edge rule to
/gamedata/ and keep respect_origin, so the nginx header wins and a 404
(notably no-store from the gamedata 404 handler) is never pinned.
This commit is contained in:
openhands committed 2026-10-01 18:00:48 +02:00
1 parent dbaccd7cfc
commit 8a6d92afd8
1 file changed
+15 -7
+15 -7
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
# Create/update the Cloudflare Cache Rule that stores the CMS public API
# allowlist at the edge (the routes nginx tags with `Cache-Tag: cms-public`).
# allowlist plus the client-facing gamedata tree at the edge (the routes nginx
# tags with `Cache-Tag: cms-public` respectievelijk `cms-gamedata`).
#
# Why a rule is required: Cloudflare only caches a handful of file extensions
# by default; `/api/*` responses are served `cf-cache-status: DYNAMIC` even
@@ -8,12 +9,19 @@
# with "Cache Everything" turns those the other way.
#
# What the rule does:
# - edge_ttl bypass_by_default : edge cachet volgens de s-maxage van nginx;
# zonder (publieke) header (bv. errorresponses) juist NIET cachen.
# - edge_ttl bypass_by_default : edge cachet volgens de max-age/s-maxage van
# nginx; zonder (publieke) header (bv. errorresponses) juist NIET cachen.
# - browser_ttl respect_origin : de zone heeft "Browser Cache TTL = 1 jaar" en
# overschrijft daarmee het max-age dat nginx per klasse stuurt. Deze rule
# herstelt dat voor de publieke API's: browsers krijgen de korte
# max-age van nginx terug (10/60/300s) i.p.v. een jaar stale data.
# herstelt dat voor de publieke API's én /gamedata/: browsers krijgen de
# per-klasse max-age van nginx terug i.p.v. een jaar stale data.
#
# Het /gamedata/-deel is toegevoegd omdat de zone-TTL anders ook de iconen
# (`.png`, een standaard cachebare extensie) op een jaar zette: nginx stuurde
# 300/3600/604800, maar de browser kreeg `max-age=31536000` en een 404 werd als
# `max-age=31536000` + `cf-cache-status: HIT` vastgezet. Een ontbrekend icon dat
# later werd geïmporteerd bleef daardoor een jaar 404. Met `respect_origin` geldt
# de nginx-header, en die stuurt op een 404 juist `no-store`.
#
# Idempotent: vergelijkt de bestaande rule (op description + inhoud) en zet
# alleen bij als die verschilt. Re-running is veilig.
@@ -27,12 +35,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"
BASE="https://api.cloudflare.com/client/v4"
PHASE="http_request_cache_settings"
DESCRIPTION="EpicNabbo CMS public API edge cache (cms-public)"
DESCRIPTION="EpicNabbo CMS public API + gamedata edge cache (cms-public, cms-gamedata)"
# Cache de allowlist exact zoals nginx hem tagt (deployment/proxy/nginx-cms.conf).
# Geen regex: `matches` vereist Business; vrije operators zijn `in` en
# `starts_with()`.
EXPRESSION='(http.request.method eq "GET") and (http.request.uri.path in { "/api/staff" "/api/teams" "/api/guilds" "/api/photos" "/api/leaderboard" "/api/online" "/api/online/count" "/api/shop" "/api/shop/categories" "/api/values" "/api/values/categories" "/api/radio/current-dj" "/api/radio/points/leaderboard" } or starts_with(http.request.uri.path, "/api/values/"))'
EXPRESSION='(http.request.method eq "GET") and (http.request.uri.path in { "/api/staff" "/api/teams" "/api/guilds" "/api/photos" "/api/leaderboard" "/api/online" "/api/online/count" "/api/shop" "/api/shop/categories" "/api/values" "/api/values/categories" "/api/radio/current-dj" "/api/radio/points/leaderboard" } or starts_with(http.request.uri.path, "/api/values/") or starts_with(http.request.uri.path, "/gamedata/"))'
load_env() {
local name="$1"