我在中间件函数中写入 cookie 时遇到问题。
我有多个中间件功能链接起来:
import { chain } from '@/middlewares/chain';
import { intlMiddleware } from '@/middlewares/intl_middleware';
import { authMiddleware } from '@/middlewares/auth_middleware';
import { localUrlMiddleware } from '@/middlewares/localURL_middleware';
export default chain([
localUrlMiddleware,
// authMiddleware,
intlMiddleware,
// add more middlewares here
])
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico|images/).*)']
}
我遇到的问题是第一个:
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server'
import { Locale, i18nConfig } from '@/lib/translations/i18n.config'
import { match as matchLocale } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
function getLocale(request: NextRequest): string {
const cookieStore = request.cookies
console.log('Cookies:', cookieStore);
const localeCookie = cookieStore.get('NEXT_LOCALE')?.toString();
if (localeCookie) {
console.log('Locale cookie:', localeCookie);
return localeCookie
}
const negotiatorHeaders: Record<string, string> = {}
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value))
console.log('Negotiator headers:', negotiatorHeaders);
// @ts-ignore locales are readonly
const locales: string[] = i18nConfig.locales
const languages = new Negotiator({ headers: negotiatorHeaders }).languages()
console.log('Preferred languages:', languages);
const locale = matchLocale(languages, locales, i18nConfig.defaultLocale)
console.log('Matched locale:', locale);
cookieStore.set({
name: 'NEXT_LOCALE',
value: locale,
})
return locale
}
export function localUrlMiddleware(nextMiddleware: NextMiddleware) {
return async (request: NextRequest, event: NextFetchEvent) => {
console.log('localUrl middleware called!');
const pathname = request.nextUrl.pathname
console.log('pathname:', pathname)
const pathnameIsMissingLocale = i18nConfig.locales.every(
locale => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
const locale = getLocale(request)
console.log('missing locale in url, attributing one:', locale);
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`,
request.url
)
)
}
return nextMiddleware(request, event);
}
}
getLocale 函数查找 NEXT_LOCALE cookie,如果没有,则设置一个新的。 然而,cookie 永远不会被写下来!
这是
的输出 const cookieStore = request.cookies
console.log('Cookies:', cookieStore);
当用户注销时,我有:
Cookies: RequestCookies {}
登录时间:
Cookies: RequestCookies {"next-auth.csrf-token":{"name":"next-auth.csrf-token","value":"1e7c35197cf1706cdcad5b55529c4712af49fb719893fe744bef32523c0997a5|034e93b1da0508b7543836bdb078e0655c2cca1ef5624145607f5f648b5c8813"},"next-auth.callback-url":{"name":"next-auth.callback-url","value":"http://localhost:3000/"},"next-auth.session-token":{"name":"next-auth.session-token","value":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..hush7RTHSXT_bw6_.onjonce2DiODfa32mghhdaZttzTKWC8EwODsWE7rl5jDjy8L8LyNAFdHlWoSxUQMEuu8_LcKZI1u9quaR1YRf8M_1JX51DG_Ta42F7QnS3BTXHGJE1ISQLDUCeDLoDz8B6EKxU0CvgPK_DizrryO5_bU9cTDUr6EbsUcIBbP_u-DDgzNjvO1Teqk2g23vF5pXmsN4EHMpz866OiP-hHg86XlHFnZM19Rdqqo0QkFSDpNo6iAyOsj3y1R6VD-4b7r5A5evEEkBcBZjXvDKyRSCtxA4XfY-MoJJakQy1XRrv_h-ueBxStMkO3EPIdOosbC60AG-WeIi5oBf_PBzOFILk8PDiOs1_KTkLKIYx59WUxUs7ph8ExUhcbMvqZR8cR4UiO0.fCFvcQxGWWqK5sc3XSFDQg"}}
我认为错误是我解释cookie的方式导致写入失败,但我不知道如何修复...
你能帮我吗?
你找到解决办法了吗?就我而言,我使用 next-intl 进行国际化,但如果用户已连接(使用 Supabase),我想在使用 next-intl 的中间件之前设置 NEXT_LOCALE cookie。如果它与导航器或位置中设置的语言相关联,则允许用户使用首选语言。
这就是我的真实情况
middleware
:
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
import { NextRequest, NextResponse } from 'next/server'
import createIntlMiddleware from 'next-intl/middleware'
import { User } from './types/type.user';
const locales = ['en', 'fr'];
const intlMiddleware = createIntlMiddleware({
locales,
defaultLocale: 'en',
localePrefix: 'never',
})
export async function middleware(req: NextRequest) {
const res = NextResponse.next()
const supabase = createMiddlewareClient({ req, res })
const { data: { session } } = await supabase.auth.getSession();
const { data: user } = await supabase.from('user').select('*').eq('id', session?.user.id).single() as { data: User }
if (user) {
res.cookies.set(
{
name: 'NEXT_LOCALE',
value: user.language,
maxAge: 365 * 24 * 60 * 60,
path: '/',
sameSite: 'strict',
priority: 'medium'
});
}
return intlMiddleware(req);
}
export const config = {
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
}
在此示例中,cookie 永远不会改变。但是如果我在 intMiddleware(req) 之前返回 res 变量,则 cookie 被设置(但显然 intlMiddleware 永远不会被调用)