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

Axios响应拦截器带数据PUT超时,无数据时触发401问题

问题分析与解决方案

核心问题

携带数据的PUT请求在access_token过期时,Django服务器返回401,但Axios触发5000ms超时错误;无数据的PUT请求则能正常触发401拦截逻辑。

可能原因

  1. 服务器响应延迟:Django处理带请求体的401响应时,可能先解析请求体再执行权限验证,导致响应时间超过Axios设置的超时阈值。
  2. Axios拦截器逻辑缺陷:请求拦截器错误处理未正确返回Promise,全局access_token变量引发竞态问题;响应拦截器未针对超时错误做针对性处理。
  3. 请求头配置问题:初始化时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',
    # 其他处理请求体的中间件放在后面
]

验证步骤

  1. 用Postman测试带数据的PUT请求,确认access_token过期时服务器返回401的响应时间在超时阈值内。
  2. 应用修改后重新测试,验证带数据的PUT请求能正常触发401拦截与token刷新逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:20:07