From 52a735f83a4208555262b141028014e9433eec66 Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Sat, 1 Aug 2026 06:26:36 +0200 Subject: [PATCH] SPA-Fallback beantwortet auch HEAD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discord prueft die im Portal hinterlegte Datenschutz- und AGB-Adresse mit einer HEAD-Anfrage. Der Fallback behandelte nur GET, alles andere lief in reply.code(404) — Discord bekam eine 404 und lehnte die Adresse mit "URL ist nicht erlaubt" ab. Im Cloudflare-Log nachgewiesen: 35.190.130.193 (Google LLC, dort laeuft Discord), python-requests, Methode HEAD, Pfad /datenschutz, und ausdruecklich "nicht eingedaemmt" — Cloudflare hat also durchgelassen, die 404 kam von uns. Damit sind auch zwei Verdaechtigungen vom Tisch: weder Bot Fight Mode (war ohnehin aus) noch AI Crawl Control. Letzteres hatte nur meine eigenen Abrufe geblockt, was mich faelschlich glauben liess, der RSS-Feed sei fuer alle tot. Er ist es nicht. Geprueft gegen den echten Fastify-Aufbau, ueber eine echte TCP-Verbindung statt app.inject(): HEAD /datenschutz und /impressum liefern 200, text/html, korrekte Content-Length und keinen Rumpf. API-Pfade bleiben unangetastet (HEAD /api/settings weiter 401). Co-Authored-By: Claude Fable 5 --- src/web/server.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/web/server.js b/src/web/server.js index 01bfc21..0b63566 100644 --- a/src/web/server.js +++ b/src/web/server.js @@ -210,7 +210,12 @@ export async function startWebServer(client) { const isApiPath = ['/api', '/auth', '/webhooks', '/sso'].some((p) => request.url.startsWith(p) ); - if (request.method === 'GET' && !isApiPath) { + // HEAD gehört dazu: Prüfer, die nur die Erreichbarkeit testen, + // fragen so an — Discord etwa, wenn du im Portal eine Datenschutz- + // oder AGB-Adresse hinterlegst. Ohne HEAD kam dort eine 404 zurück + // und Discord lehnte die Adresse als „nicht erlaubt" ab. + // Node lässt den Rumpf bei HEAD von selbst weg. + if ((request.method === 'GET' || request.method === 'HEAD') && !isApiPath) { return sendInjected(request, reply); } return reply.code(404).send({ error: 'not found' });