You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将fetch()响应中的Set-Cookie复制到Next.js 13中间件响应?

问题:Next.js 13中间件简化Cookie传递处理

我正在编写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)

解决方案:直接解析Set-Cookie头复用属性

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 03:50:58