fix(gamedata): never cache a missing gamedata file
A missing gamedata file got no Cache-Control at all, because add_header without `always` only applies to 2xx/3xx. Cloudflare then fell back to the zone setting "Browser Cache TTL = 1 year", so the 404 came back as `max-age=31536000` with `cf-cache-status: HIT` — pinned in the visitor's browser and at the edge. An icon requested while its import was still running stayed a 404 for the rest of the year, even after the file existed. That was the "some icons load, some don't" report. Give every gamedata location a named 404 handler that sends no-store, and split icons/ out as its own cache class: those files are rewritten under the same name (repair-icons, reimport), so an hourly must-revalidate keeps a repaired icon visible within the hour instead of days later.
This commit is contained in:
1 parent
4e036b08d5
commit
dbaccd7cfc
1 file changed
+53
-7
@@ -192,7 +192,7 @@ server {
|
|||||||
keepalive_timeout 30s;
|
keepalive_timeout 30s;
|
||||||
send_timeout 10s;
|
send_timeout 10s;
|
||||||
|
|
||||||
# Abuse limits. Deliberately NOT set at server scope: a room load and a page
|
# Abuse limits. Deliberately NOT set at server scope: a room load and a page
|
||||||
# load are not the same request profile, so each location picks its own zone.
|
# load are not the same request profile, so each location picks its own zone.
|
||||||
# /gamedata/* has no request limit at all — it is a disk cache, so limiting
|
# /gamedata/* has no request limit at all — it is a disk cache, so limiting
|
||||||
# it only cost players their icons. The page routes carry the budget.
|
# it only cost players their icons. The page routes carry the budget.
|
||||||
@@ -242,7 +242,7 @@ server {
|
|||||||
location = /gamedata { return 301 /gamedata/config/; }
|
location = /gamedata { return 301 /gamedata/config/; }
|
||||||
location = /gamedata/ { return 301 /gamedata/config/; }
|
location = /gamedata/ { return 301 /gamedata/config/; }
|
||||||
|
|
||||||
# ─── Gamedata: drie cache-klassen, want niet alles onder /gamedata/ is
|
# ─── Gamedata: vier cache-klassen, want niet alles onder /gamedata/ is
|
||||||
# even veranderlijk.
|
# even veranderlijk.
|
||||||
#
|
#
|
||||||
# Dit pad had één regel voor de hele boom: `max-age=604800` (7 dagen). De
|
# Dit pad had één regel voor de hele boom: `max-age=604800` (7 dagen). De
|
||||||
@@ -259,7 +259,13 @@ server {
|
|||||||
# dat de bestandsnaam verandert (schalen, repareren), dus
|
# dat de bestandsnaam verandert (schalen, repareren), dus
|
||||||
# ook revalideren, maar minder vaak: ze worden veel vaker
|
# ook revalideren, maar minder vaak: ze worden veel vaker
|
||||||
# opgehaald dan ze worden geschreven.
|
# opgehaald dan ze worden geschreven.
|
||||||
# 3. alles wat overblijft (c_images, album*, clothes, …) — content-addressed
|
# 3. icons/ — `{classname}_icon.png`. Wordt wél herschreven onder
|
||||||
|
# dezelfde naam (repair-icons.ts, herimport), dus ook
|
||||||
|
# klasse 4's "nooit herschreven" geldt hier niet. Wel
|
||||||
|
# minder vaak dan 2: per uur een must-revalidate is één
|
||||||
|
# 304 per icon per uur, en een gerepareerd icon is zo
|
||||||
|
# binnen een uur zichtbaar in plaats van dagenlang oud.
|
||||||
|
# 4. alles wat overblijft (c_images, album*, clothes, …) — content-addressed
|
||||||
# of per item uniek, nooit herschreven onder dezelfde naam. Blijft lang.
|
# of per item uniek, nooit herschreven onder dezelfde naam. Blijft lang.
|
||||||
location ^~ /gamedata/config/ {
|
location ^~ /gamedata/config/ {
|
||||||
alias /var/www/Gamedata/config/;
|
alias /var/www/Gamedata/config/;
|
||||||
@@ -267,10 +273,6 @@ server {
|
|||||||
access_log off;
|
access_log off;
|
||||||
add_header Cache-Tag "cms-gamedata";
|
add_header Cache-Tag "cms-gamedata";
|
||||||
|
|
||||||
# Geen limit_req: gamedata is schijf-cache, geen CMS-backend. Een
|
|
||||||
# kamerladen vuurt honderden bestanden in één burst af en elke limiet
|
|
||||||
# hier leidde alleen tot zichtbaar gemiste icons.
|
|
||||||
|
|
||||||
add_header Access-Control-Allow-Origin $http_origin always;
|
add_header Access-Control-Allow-Origin $http_origin always;
|
||||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||||
if ($cors_headers) {
|
if ($cors_headers) {
|
||||||
@@ -278,6 +280,7 @@ server {
|
|||||||
add_header Content-Type "text/plain; charset=utf-8";
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
return 204;
|
return 204;
|
||||||
}
|
}
|
||||||
|
error_page 404 = @gamedata_missing;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ^~ /gamedata/bundled/ {
|
location ^~ /gamedata/bundled/ {
|
||||||
@@ -286,6 +289,22 @@ server {
|
|||||||
access_log off;
|
access_log off;
|
||||||
add_header Cache-Tag "cms-gamedata";
|
add_header Cache-Tag "cms-gamedata";
|
||||||
|
|
||||||
|
add_header Access-Control-Allow-Origin $http_origin always;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||||
|
if ($cors_headers) {
|
||||||
|
add_header Access-Control-Max-Age 1728000;
|
||||||
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
error_page 404 = @gamedata_missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /gamedata/icons/ {
|
||||||
|
alias /var/www/Gamedata/icons/;
|
||||||
|
add_header Cache-Control "public, max-age=3600, must-revalidate";
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Tag "cms-gamedata";
|
||||||
|
|
||||||
# Geen limit_req: gamedata is schijf-cache, geen CMS-backend. Een
|
# Geen limit_req: gamedata is schijf-cache, geen CMS-backend. Een
|
||||||
# kamerladen vuurt honderden bestanden in één burst af en elke limiet
|
# kamerladen vuurt honderden bestanden in één burst af en elke limiet
|
||||||
# hier leidde alleen tot zichtbaar gemiste icons.
|
# hier leidde alleen tot zichtbaar gemiste icons.
|
||||||
@@ -297,6 +316,7 @@ server {
|
|||||||
add_header Content-Type "text/plain; charset=utf-8";
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
return 204;
|
return 204;
|
||||||
}
|
}
|
||||||
|
error_page 404 = @gamedata_missing;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /gamedata/ {
|
location /gamedata/ {
|
||||||
@@ -312,6 +332,32 @@ server {
|
|||||||
add_header Content-Type "text/plain; charset=utf-8";
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
return 204;
|
return 204;
|
||||||
}
|
}
|
||||||
|
error_page 404 = @gamedata_missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Een ONTBREKEND gamedata-bestand mag nooit gecacht worden, en daarom
|
||||||
|
# krijgt elke 404 hier een eigen handler.
|
||||||
|
#
|
||||||
|
# Zonder deze handler stuurde nginx op een 404 helemaal geen Cache-Control:
|
||||||
|
# `add_header` geldt zonder `always` alleen voor 2xx/3xx. Cloudflare vond
|
||||||
|
# dan geen expliciete cache-instructie en nam de zone-instelling over:
|
||||||
|
# "Browser Cache TTL = 1 jaar". Gevolg: de 404 kwam terug als
|
||||||
|
# `cache-control: max-age=31536000` met `cf-cache-status: HIT` — dus
|
||||||
|
# vastgezet in de browser van de bezoeker én op de edge. Een icon dat één
|
||||||
|
# keer te vroeg werd opgevraagd (import nog bezig) bleef daarom het hele
|
||||||
|
# jaar een 404, ook nadat het bestand er wél stond. Dat was de "sommige
|
||||||
|
# icons laden wel, sommige niet"-klacht.
|
||||||
|
#
|
||||||
|
# `no-store` (niet een korte TTL): het bestand kan elk moment verschijnen,
|
||||||
|
# dus er is geen enkel venster waarin we een 404 willen vasthouden. De
|
||||||
|
# Cache-Tag blijft meegegeven zodat een al gecachte 404 alsnog te purgen is
|
||||||
|
# via `scripts/cf-purge.sh cms-gamedata`.
|
||||||
|
location @gamedata_missing {
|
||||||
|
add_header Cache-Control "no-store" always;
|
||||||
|
add_header Cache-Tag "cms-gamedata" always;
|
||||||
|
add_header Access-Control-Allow-Origin $http_origin always;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||||
|
return 404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /camera/ {
|
location /camera/ {
|
||||||
|
|||||||
Reference in new issue
Block a user