我需要为多语言站点实现基于 cookie 的重定向逻辑。我有 Next.js 中间件的工作代码,但不幸的是它无法在 Docker 的独立设置中工作(我不使用 Vercel)。
import { NextRequest, NextResponse } from 'next/server';
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next (static files)
* - URLs ending with a file extension (e.g., .html, .js, .css, etc.)
*/
'/((?!api|_next|\\.\\.).+)',
],
};
export function middleware(request: NextRequest) {
const { pathname, search, defaultLocale, locale } = request.nextUrl;
const localeCookie = request.cookies.get('NEXT_LOCALE')?.value;
if (!localeCookie && locale !== defaultLocale) {
return NextResponse.redirect(new URL(`/${defaultLocale}${pathname}${search}`, request.url));
}
if (localeCookie && locale !== localeCookie) {
return NextResponse.redirect(new URL(`/${localeCookie}${pathname}${search}`, request.url));
}
return NextResponse.next();
}
我想实现 Varnish 设置而不是 Next.js 解决方案:
vcl 4.1;
import cookie;
sub vcl_recv {
...
if (req.url ~ "^/_next" || req.url ~ "/api/" || req.url ~ "/\.(.*)$/") {
return (pass);
}
# Extract the locale from the URL, the default locale is hidden
if (req.url ~ "^/[a-z]{2}/") {
set req.http.locale = regsub(req.url, "^/([a-z]{2})(/.*)?$", "\1");
} else {
set req.http.locale = "";
}
# Extract NEXT_LOCALE cookie
if (req.http.cookie) {
cookie.parse(req.http.cookie);
set req.http.localeCookie = cookie.get("NEXT_LOCALE");
set req.http.cookie = cookie.get_string();
}
// If locale is specified and NEXT_LOCALE is missing, redirect to the default locale.
if (req.http.locale != "" && !req.http.localeCookie) {
# set req.http.X-Redirect-Url = ...;
return (synth(302));
}
// If NEXT_LOCALE is present and the locale is not equal to the locale from cookie, then redirect to the cookie locale
else if (req.http.locale != "" && req.http.locale != req.http.localeCookie) {
# set req.http.X-Redirect-Url = ...;
return (synth(302));
}
...
return (hash);
}
sub vcl_synth {
# Perform the actual redirection based on the X-Redirect-Url header
if (resp.status == 302 && req.http.X-Redirect-Url) {
set resp.http.location = req.http.X-Redirect-Url;
set resp.reason = "Moved";
return (deliver);
}
}