如何将fetch()响应中的Set-Cookie复制到Next.js 13中间件响应?
我正在编写Next.js 13的中间件,当前代码需要从sessionLogin接口的响应头中提取Cookie值,再手动重复设置所有Cookie属性到响应里,这种方式冗余繁琐。我希望能直接获取接口响应中的Cookie配置,再直接应用到中间件的响应中,不用手动处理每个属性。
原中间件代码:
// middleware.js import { cookies } from "next/headers" import { NextResponse } from "next/server" export async function middleware(request) { const { pathname, origin, search, searchParams } = request.nextUrl let response = NextResponse.next() // 如果搜索参数包含refreshIDToken=true,调用sessionLogin接口刷新用户ID Token if (searchParams.get("refreshIDToken") === "true") { // 获取当前会话Cookie const sessionCookie = cookies().get("sessionCookie") // 重新登录,返回新的会话Cookie const sessionLoginResponse = await fetch(`${origin}/api/sessionLogin`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify({ idToken: sessionCookie.value }), }) // === 想要重构的代码开始 ===================== // 提取Cookie并附加到响应中 const sessionCookieHeader = sessionLoginResponse.headers.getSetCookie()[0] const sessionCookieVal = /^sessionCookie=([^;]+)/.exec( sessionCookieHeader ) if (sessionCookieVal) { response.cookies.set({ name: "sessionCookie", value: sessionCookieVal[1], maxAge: 60 * 60 * 24 * 5 * 1000, sameSite: "lax", httpOnly: true, secure: true, path: "/", }) } // === 想要重构的代码结束 ===================== } return response }
我希望能实现类似这样的简化写法,但不知道怎么操作:
const newSessionCookie = sessionLoginResponse.cookies.get("sessionCookie") response.cookies.set("sessionCookie", newSessionCookie)
fetch返回的Response对象没有内置的cookies属性,所以需要手动解析Set-Cookie头中的完整配置,再直接传递给response.cookies.set()。
步骤1:编写Set-Cookie解析函数
这个函数会把Set-Cookie字符串解析成response.cookies.set()支持的配置对象:
function parseSetCookieHeader(setCookieStr) { const parts = setCookieStr.split(';').map(part => part.trim()) const [nameValuePair] = parts const [name, value] = nameValuePair.split('=').map(part => part.trim()) const cookieOptions = {} for (const part of parts.slice(1)) { if (part.startsWith('Max-Age=')) { cookieOptions.maxAge = parseInt(part.split('=')[1], 10) } else if (part.startsWith('Expires=')) { cookieOptions.expires = new Date(part.split('=')[1]) } else if (part.startsWith('Path=')) { cookieOptions.path = part.split('=')[1] } else if (part.startsWith('Domain=')) { cookieOptions.domain = part.split('=')[1] } else if (part === 'HttpOnly') { cookieOptions.httpOnly = true } else if (part === 'Secure') { cookieOptions.secure = true } else if (part.startsWith('SameSite=')) { cookieOptions.sameSite = part.split('=')[1] } } return { name, value, ...cookieOptions } }
步骤2:在中间件中替换原有代码
用解析函数处理接口返回的Set-Cookie头,直接复用所有属性:
// === 重构后的代码 ===================== const setCookieHeaders = sessionLoginResponse.headers.getSetCookie() // 找到目标sessionCookie的头信息 const sessionCookieHeader = setCookieHeaders.find(header => header.startsWith('sessionCookie=')) if (sessionCookieHeader) { const cookieData = parseSetCookieHeader(sessionCookieHeader) response.cookies.set(cookieData) } // === 重构后的代码结束 =====================
扩展:批量处理多个Cookie
如果接口返回多个Cookie,可遍历所有Set-Cookie头批量设置:
setCookieHeaders.forEach(header => { const cookieData = parseSetCookieHeader(header) response.cookies.set(cookieData) })
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

