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);