Next.js API路由Axios请求时redirect重定向到登录页失效如何解决
根因说明
该问题的核心是浏览器对不同类型请求的重定向处理逻辑存在差异:
- 直接在浏览器地址栏发起的是页面导航类请求,浏览器收到3xx响应后会自动执行全局页面跳转
- Axios发起的是XHR异步请求,浏览器默认会自动跟随重定向获取目标地址的内容,不会触发当前页面的全局跳转,因此后端返回307不会产生预期的跳转效果
解决方案
1. 调整Next.js后端API逻辑
不再返回307重定向,改为返回401未授权状态码,方便前端识别会话失效场景:
// pages/api/xxx.js 会话无效时的处理逻辑 if (!sessionValid) { return res.status(401).json({ code: 401, msg: "会话已失效,请重新登录", redirectUrl: "/login" }) }
2. 给Axios添加全局响应拦截器
在前端Axios的初始化位置添加拦截逻辑,捕获401状态后主动执行页面跳转:
import axios from 'axios' import Router from 'next/router' // 添加响应拦截器 axios.interceptors.response.use( (response) => response, (error) => { // 捕获会话失效的401状态码 if (error.response && error.response.status === 401) { // 清除本地存储的会话、用户信息 localStorage.removeItem('token') localStorage.removeItem('userInfo') // 主动跳转到登录页 Router.push(error.response.data.redirectUrl || '/login') } return Promise.reject(error) } )
可选兼容方案
如果必须保留后端返回307的逻辑,可关闭Axios的自动跟随重定向配置,再在拦截器中处理跳转:
// 初始化Axios时关闭自动重定向 const instance = axios.create({ maxRedirects: 0 }) // 拦截器中判断3xx状态,取Location头跳转 instance.interceptors.response.use( (response) => response, (error) => { if (error.response && [301,302,307,308].includes(error.response.status)) { const redirectUrl = error.response.headers.location Router.push(redirectUrl || '/login') } return Promise.reject(error) } )
该方案容易出现跨域等额外问题,更推荐优先使用401状态码的方案。
内容的提问来源于stack exchange,提问作者Jules Grenier
相关产品推荐
相关产品推荐

