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

Next.js中间件修改自定义Fetch请求头无效?SSR添加Cookie求助

Next.js SSR中通过中间件设置请求头Cookie不生效的原因及解决办法

我想在Next.js的服务端渲染(SSR)过程中给请求头自动添加Cookie,现在已经封装了自定义API模块简化Fetch调用:

// custom-api.ts
export const headers = new Headers({
    credentials: 'include',
});

const api = {
    get: async(path: string, options?: any) => {
        const res = await fetch(`${path}`, {
                headers,
                ...options,
            });

        return await res.json();
    },
};

但在SSR时,每次都得在getServerSideProps里手动设置请求头,操作太繁琐:

// import { getData } from '@/services/main';
export const getServerSideProps = async (context) => {
    const { cookies } = context.req;

    const queryClient = new QueryClient();
    queryClient.prefetchQuery(['query-key'], getData);
    
    return { props: {} };
};

于是尝试用中间件处理,但修改后的请求头没生效,想知道原因:

//src/middleware.ts
import { headers } from '@/utils/api';
export async function middleware(request: NextRequest) {
    const { cookies } = request;
    headers.set('Cookie', `my-cookie=${cookies.get('my-cookie')?.value}`); // 值能正常获取到
    NextResponse.next();
}

不生效的核心原因

  • 全局Headers实例共享冲突:你导出的headers是全局单例对象,中间件在每个请求前执行时修改它,会导致多个请求间的Cookie互相污染。而且Next.js服务端环境中,这种全局修改不会自动关联到getServerSideProps里独立发起的Fetch请求上下文。
  • 中间件作用范围不匹配:中间件负责处理客户端到Next.js服务器的入站请求,它修改的是进入Next.js的请求头,但不会直接影响你在getServerSideProps里手动创建的Fetch请求头——这些请求是Next.js服务器向外部API发起的,和中间件处理的入站请求是两个独立的请求链路。
  • 中间件代码遗漏返回值:你的中间件最后没返回NextResponse.next(),这会导致中间件逻辑根本不执行,但就算补上,也解决不了前面两个核心问题。

可行的解决方案

方案1:通过上下文传递Cookie(Pages Router推荐)

改造自定义API,让它支持接收自定义Headers,不再依赖全局单例:

// custom-api.ts
const createApi = (customHeaders?: Headers) => {
  const baseHeaders = new Headers({
    credentials: 'include',
    ...customHeaders,
  });

  return {
    get: async(path: string, options?: any) => {
      const res = await fetch(`${path}`, {
        headers: baseHeaders,
        ...options,
      });
      return await res.json();
    },
  };
};

export default createApi;

然后在getServerSideProps里创建带当前请求Cookie的API实例:

// 页面组件文件
import createApi from '@/utils/custom-api';
import { getData } from '@/services/main';

export const getServerSideProps = async (context) => {
  const { cookies } = context.req;
  // 把当前请求的所有Cookie拼接成请求头格式
  const cookieHeader = Object.entries(cookies)
    .map(([key, value]) => `${key}=${value}`)
    .join('; ');
  
  const api = createApi(new Headers({ Cookie: cookieHeader }));
  // 把api实例传给getData,让内部用这个实例发起请求
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery(['query-key'], () => getData(api));

  return { props: {} };
};

方案2:利用请求上下文自动获取(App Router推荐)

如果用的是App Router,可以在Server Component里直接用Next.js提供的headers()函数获取当前请求头,自动传递给API:

// custom-api.ts
import { headers } from 'next/headers';

export const api = {
  get: async(path: string, options?: any) => {
    // 从当前请求上下文获取完整请求头,再添加自定义配置
    const requestHeaders = new Headers(headers());
    requestHeaders.set('credentials', 'include');
    
    const res = await fetch(`${path}`, {
      headers: requestHeaders,
      ...options,
    });
    return await res.json();
  },
};

这种方式下,Server Component里的API调用会自动带上当前请求的Cookie,不需要手动处理。

内容的提问来源于stack exchange,提问作者minami

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:16:33