Axios响应拦截器带数据PUT超时,无数据时触发401问题
问题分析与解决方案
核心问题
携带数据的PUT请求在access_token过期时,Django服务器返回401,但Axios触发5000ms超时错误;无数据的PUT请求则能正常触发401拦截逻辑。
可能原因
- 服务器响应延迟:Django处理带请求体的401响应时,可能先解析请求体再执行权限验证,导致响应时间超过Axios设置的超时阈值。
- Axios拦截器逻辑缺陷:请求拦截器错误处理未正确返回Promise,全局
access_token变量引发竞态问题;响应拦截器未针对超时错误做针对性处理。 - 请求头配置问题:初始化时
Authorization头携带无效的Bearer null,干扰服务器验证流程。
分步解决方案
1. 修复Axios请求拦截器逻辑
移除全局access_token变量,动态配置请求头并修正错误处理:
instance.interceptors.request.use( async (config) => { const atoken = await SecureStore.getItemAsync("access_token"); if (atoken) { config.headers.Authorization = `Bearer ${atoken}`; } else { // 删除无效的Authorization头,避免干扰服务器验证 delete config.headers.Authorization; } return config; }, (error) => { // 必须返回Promise.reject,确保错误能被后续捕获 return Promise.reject(error); } );
2. 优化响应拦截器的超时与401处理
增加超时错误判断与重试逻辑,确保401能被正确捕获:
instance.interceptors.response.use( (response) => { return response; }, async (error) => { const originalConfig = error.config; // 处理超时错误,允许重试一次 if (error.code === 'ECONNABORTED') { if (!originalConfig._retry) { originalConfig._retry = true; return instance(originalConfig); } alert("请求超时,请稍后重试。"); return Promise.reject(error); } if (typeof error.response === "undefined") { alert("服务器/网络错误。"); return Promise.reject(error); } else if (error.response.status === 401 && !originalConfig._retry) { originalConfig._retry = true; await refreshAccessToken(); return instance(originalConfig); } else { return Promise.reject(error); } } );
3. 调整Axios超时时间
适当延长超时阈值,给服务器足够时间返回401响应:
const instance = axios.create({ baseURL: baseURL, xsrfHeaderName: "X-CSRFTOKEN", xsrfCookieName: "csrftoken", timeout: 10000, // 从5000ms调整为10000ms headers: { "Content-Type": "application/json", accept: "*/*", }, });
4. 优化Django中间件顺序(服务器端)
确保权限验证在请求体解析之前执行,减少响应延迟:
在settings.py中调整中间件顺序,将AuthenticationMiddleware放在处理请求体的中间件之前:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', # 先执行权限验证,再解析请求体 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 其他处理请求体的中间件放在后面 ]
验证步骤
- 用Postman测试带数据的PUT请求,确认
access_token过期时服务器返回401的响应时间在超时阈值内。 - 应用修改后重新测试,验证带数据的PUT请求能正常触发401拦截与token刷新逻辑。
内容的提问来源于stack exchange,提问作者steve johnson
相关产品推荐
相关产品推荐

