import { type NextMiddleware, NextResponse } from "next/server" import { getCacheClient } from "@scandic-hotels/common/dataCache" import { logger } from "@scandic-hotels/common/logger" import { createCounter } from "@scandic-hotels/common/telemetry" import { findLang } from "@scandic-hotels/common/utils/languages" import { notFound } from "@/server/errors/next" import { getPublicNextURL } from "@/server/utils" import { getDefaultRequestHeaders } from "./utils" import type { Lang } from "@scandic-hotels/common/constants/language" import type { MiddlewareMatcher } from "@/types/middleware" async function fetchAndCacheRedirect(lang: Lang, pathname: string) { const cacheKey = `${lang}:redirect:${pathname}` const cache = await getCacheClient() return await cache.cacheOrGet( cacheKey, async () => { const matchedRedirect = await fetch( "https://redirect-scandic-hotels.netlify.app", { method: "POST", body: JSON.stringify({ lang, pathname }), headers: { "Content-Type": "application/json", }, signal: AbortSignal.timeout(15_000), } ) if (matchedRedirect.ok) { const result = await matchedRedirect.text() if (result) { return result } } return null }, // longer once tested "1d" ) } const redirectCounter = createCounter("middleware.redirect") export const middleware: NextMiddleware = async (request) => { const lang = findLang(request.nextUrl.pathname)! const headers = getDefaultRequestHeaders(request) try { const matchedRedirect = await fetchAndCacheRedirect( lang, request.nextUrl.pathname ) if (matchedRedirect) { redirectCounter .init({ lang, pathname: request.nextUrl.pathname, newPathname: matchedRedirect, }) .success() const newUrl = new URL(matchedRedirect, getPublicNextURL(request)) headers.set("Cache-control", "public, max-age=14400") // 4 hours return NextResponse.redirect(newUrl, { headers, status: 308, }) } headers.set("x-continue", "1") return NextResponse.next({ headers }) } catch (e) { logger.error("Redirect error: ", e) throw notFound() } } export const matcher: MiddlewareMatcher = (_) => { return true }