From 3b3069457317b71ede49ccc64e70504203b6d551 Mon Sep 17 00:00:00 2001 From: Jan Wagner Date: Mon, 31 Aug 2026 21:21:06 +0200 Subject: [PATCH] fix(proxy): OG-Image und Next-Special-Routes vom Locale-Rewrite ausnehmen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vorher: /de/projects/hermes/opengraph-image wurde vom Proxy auf /projekte/hermes (die Page, nicht das OG-Image) redirected. Grund: toPublicFromInternal('/de/projects/hermes/opengraph-image') hat den Path '/de/projects/hermes' als 'about' gemappt und '/projekte/hermes' zurückgegeben — ohne Beachtung des '/opengraph-image'-Suffixes. Result: Crawler (Twitter, LinkedIn, Slack) konnten die OG-Images nicht mehr abrufen, sie haben 307 bekommen statt 200. Fix: Im Proxy eine 'isNextSpecialRoute'-Prüfung VOR dem Locale-Rewrite eingefügt. Routen mit Suffix wie 'opengraph-image', 'twitter-image', 'sitemap.xml', 'robots.txt', 'icon', 'apple-icon' werden direkt zum nächsten Handler durchgelassen — kein Redirect, kein Rewrite. Damit: - /de/projects/hermes/opengraph-image → 200 (PNG, OG-Image) - /de/projects/hermes/twitter-image → 200 (PNG, Twitter-Image, wenn vorhanden) - /sitemap.xml → 200 (statisch, wie vorher) - /robots.txt → 200 (statisch) - Normale Locale-Rewrites für /de/... und public → //... funktionieren weiterhin. --- src/proxy.ts | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index a4fe5f6..482b63b 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1,10 +1,31 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; -import { defaultLocale, isLocale, resolvePublicPath, toInternalPath, toPublicFromInternal, switchLocale } from "@/i18n/routes"; +import { defaultLocale, isLocale, resolvePublicPath, toInternalPath, toPublicFromInternal } from "@/i18n/routes"; import { readCookieFromHeader } from "@/lib/auth/cookie"; import { verifySession } from "@/lib/auth/session"; -const PUBLIC_FILE = /\.(?:svg|png|jpg|jpeg|gif|webp|ico|txt|xml|json|css|js|map)$/; +// Next.js-Konvention: opengraph-image/twitter-image/etc. sind Spezial-Routes, +// die unter einer Page hängen aber als eigene URL exposed werden (mit eigenem +// Segment nach dem Slug). Sie dürfen NICHT von unserem Locale-Rewrite zu einer +// anderen URL umgebogen werden — sonst liefert der Proxy 307 auf die Page. +const NEXT_SPECIAL_SUFFIXES = [ + "opengraph-image", + "twitter-image", + "sitemap.xml", + "robots.txt", + "icon", + "apple-icon", + "manifest.webmanifest", +]; + +function isNextSpecialRoute(pathname: string): boolean { + // /de/projects/hermes/opengraph-image → matcht "opengraph-image" + // /api/... → matcht nichts (sollte gar nicht hier landen, der Proxy-Rewrite + // hat eigene Regeln) + const segments = pathname.split("/").filter(Boolean); + const last = segments[segments.length - 1] ?? ""; + return NEXT_SPECIAL_SUFFIXES.includes(last); +} function isAdminLoginPath(pathname: string): boolean { return pathname === "/admin/login" || pathname.startsWith("/admin/login/"); @@ -46,6 +67,12 @@ export function proxy(request: NextRequest) { } } + // Next-Special-Routes (OG-Image, Sitemap, etc.) durchlassen, ohne sie + // durch die Locale-Rewrite zu jagen — die haben ihre eigene URL. + if (isNextSpecialRoute(pathname)) { + return NextResponse.next({ request: { headers } }); + } + // /de/... → public if (pathname === "/de" || pathname.startsWith("/de/")) { const publicPath = toPublicFromInternal(pathname);