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

Next.js 15中Axios拦截器处理401调用redirect报错求助

问题:Next.js 15 + React 19中Axios拦截器调用redirect触发NEXT_REDIRECT错误

在Next.js 15和React 19项目中,尝试在Axios响应拦截器中调用Next.js的redirect方法处理401未授权错误时,触发了如下错误:

Error: NEXT_REDIRECT
    at <unknown> (file://project/apps/web/lib/axios.ts:36:15)
    at async Object.getProfile (file://project/apps/web/lib/api/user.ts:12:23)
    at async Page (file://project/apps/web/app/dashboard/page.tsx:4:22)
  34 |   async error => {
  35 |     if (error.response && error.response.status === 401)
> 36 |       redirect('/auth/login');
     |               ^
  37 |
  38 |     return Promise.reject(error);
  39 |   }, {
  digest: 'NEXT_REDIRECT;replace;/auth/login;307;'
}

需要对/dashboard下的所有请求进行401错误校验,尝试过多种方案均无效,求解决思路。

用户提供的完整Axios配置代码:

'use server';

import axios from 'axios';
import { redirect } from 'next/navigation';

import { getSession } from './session';

const baseURL = process.env.NEXT_PUBLIC_BACKEND_URL;

export const axiosInstance = axios.create({
  baseURL,
  headers: {
    'Content-Type': 'application/json',
  },
});

axiosInstance.interceptors.request.use(
  async config => {
    const session = await getSession();

    if (session && session.accessToken) {
      config.headers.Authorization = `Bearer ${session.accessToken}`;
    }

    return config;
  },
  error => {
    return Promise.reject(error);
  },
);

axiosInstance.interceptors.response.use(
  response => response,
  async error => {
    if (error.response && error.response.status === 401)
      redirect('/auth/login');

    return Promise.reject(error);
  },
);

解决思路

1. 错误本质:redirect的工作机制与Axios拦截器的冲突

Next.js的redirect函数并非直接执行跳转逻辑,而是抛出一个特殊的NEXT_REDIRECT错误,由Next.js的路由系统捕获后处理跳转。但在Axios响应拦截器中调用redirect时,这个错误会被Axios的Promise错误处理链捕获,无法传递给Next.js的服务器组件/服务器动作上下文,因此直接暴露为未处理错误。

2. 可行解决方案

方案一:在API调用处统一捕获401并执行跳转

移除Axios拦截器中的redirect调用,改为抛出自定义标识的错误,然后在调用API的业务代码中捕获并处理跳转:

  • 修改Axios响应拦截器:

    axiosInstance.interceptors.response.use(
      response => response,
      async error => {
        if (error.response && error.response.status === 401) {
          // 抛出自定义错误标识
          return Promise.reject(new Error('UNAUTHORIZED'));
        }
        return Promise.reject(error);
      },
    );
    
  • 在Page组件或API调用函数中捕获错误:

    // app/dashboard/page.tsx
    'use server';
    import { redirect } from 'next/navigation';
    import { getProfile } from '@/lib/api/user';
    
    export default async function Page() {
      try {
        const profile = await getProfile();
        // 渲染页面内容
      } catch (err) {
        if (err.message === 'UNAUTHORIZED') {
          redirect('/auth/login');
        }
        // 处理其他类型错误
      }
    }
    

方案二:提前在布局层做权限校验(推荐)

针对/dashboard这类需要授权的路由,直接在布局组件的顶层校验会话有效性,避免等到API返回401再处理,更符合Next.js的路由模型:

// app/dashboard/layout.tsx
'use server';
import { redirect } from 'next/navigation';
import { getSession } from '@/lib/session';

export default async function DashboardLayout({ children }) {
  const session = await getSession();
  // 校验会话是否有效,无有效会话直接跳转登录页
  if (!session?.accessToken) {
    redirect('/auth/login');
  }
  return <div>{children}</div>;
}

这种方式能提前拦截未授权访问,减少不必要的API请求,同时避免Axios拦截器与Next.js路由系统的冲突。

方案三:封装API调用函数统一处理401

将所有API调用封装到一个统一的函数中,在函数内部处理401错误并执行跳转,替代Axios拦截器的逻辑:

// lib/api/client.ts
'use server';
import { axiosInstance } from '../axios';
import { redirect } from 'next/navigation';

export async function apiCall(method: string, url: string, data?: any) {
  try {
    const response = await axiosInstance({ method, url, data });
    return response.data;
  } catch (err) {
    if (err.response?.status === 401) {
      redirect('/auth/login');
    }
    throw err;
  }
}

使用时用apiCall代替直接调用axiosInstance:

// lib/api/user.ts
import { apiCall } from './client';

export async function getProfile() {
  return apiCall('GET', '/user/profile');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:27:25