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

在Next.js中使用原生fetch时是否有类似axios拦截器的实现方案?

Next.js 原生fetch实现拦截器方案

以下两种方案可以完美替代axios拦截器的能力,实现统一添加token、统一处理响应等逻辑:

方案1:封装自定义fetch工具(最推荐)

这种方法不会污染全局fetch,灵活度最高,客户端、服务端场景通用:

  • 第一步:新建工具文件 src/utils/fetchWithAuth.ts,写入以下逻辑:
export const fetchWithAuth = async (input: RequestInfo | URL, init?: RequestInit) => {
  // ========== 请求拦截逻辑开始 ==========
  let token: string | null = null;
  // 客户端场景从localStorage获取token
  if (typeof window !== 'undefined') {
    token = localStorage.getItem('auth_token');
  } 
  // 服务端场景(Next.js 13+ App Router)从cookie获取token
  else {
    const { cookies } = await import('next/headers');
    token = cookies().get('auth_token')?.value || null;
  }

  // 合并自定义请求头
  const headers = new Headers(init?.headers);
  if (token) {
    headers.set('Authorization', `Bearer ${token}`);
  }
  // 可根据需求添加其他公共请求头
  if (!headers.has('Content-Type')) {
    headers.set('Content-Type', 'application/json');
  }

  const modifiedInit: RequestInit = {
    ...init,
    headers
  };
  // ========== 请求拦截逻辑结束 ==========

  const response = await fetch(input, modifiedInit);

  // ========== 响应拦截逻辑开始 ==========
  // 统一处理401未授权跳转登录
  if (response.status === 401) {
    if (typeof window !== 'undefined') {
      window.location.href = '/login';
    } else {
      const { redirect } = await import('next/navigation');
      redirect('/login');
    }
  }
  // 可扩展其他响应处理逻辑:统一报错提示、格式化返回数据等
  // ========== 响应拦截逻辑结束 ==========

  return response;
};
  • 第二步:替换项目中原生fetch调用,直接使用fetchWithAuth即可,用法和原生fetch完全一致,不需要额外手动添加token:
// 示例请求
const getUserInfo = async () => {
  const res = await fetchWithAuth('/api/user/info', {
    method: 'GET'
  });
  return await res.json();
};

方案2:全局重写原生fetch

如果不想修改项目中已有的大量fetch调用,可以直接重写全局fetch方法,实现全局拦截:

客户端全局拦截

在根客户端布局文件(app/layout.tsx标记'use client')的useEffect中添加以下逻辑:

'use client';
import { useEffect } from 'react';

export default function RootLayout({ children }) {
  useEffect(() => {
    const originalFetch = window.fetch;
    window.fetch = async (input, init) => {
      // 请求拦截:统一加token
      const token = localStorage.getItem('auth_token');
      const headers = new Headers(init?.headers);
      if (token) {
        headers.set('Authorization', `Bearer ${token}`);
      }
      const modifiedInit = { ...init, headers };

      const res = await originalFetch(input, modifiedInit);

      // 响应拦截:统一处理401
      if (res.status === 401) {
        window.location.href = '/login';
      }
      return res;
    };
  }, []);

  return <html><body>{children}</body></html>
}

服务端全局拦截

如果需要服务端请求也统一加拦截,可以在middleware.ts中统一处理请求头,或者在服务端逻辑入口重写全局fetch方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:12:01