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

如何根据access_token过期状态与URL动态设置Axios请求头?

动态设置Axios请求头并处理多API的token过期问题

当然可以动态设置Axios请求头,针对你这种不同API对应不同认证token、需要在token过期时自动切换的场景,用Axios的请求拦截器和响应拦截器就能完美解决,下面直接给你改造方案:

第一步:重构token管理逻辑

首先你原来的代码里直接同步调用axios.get拿token是错误的,因为axios请求是异步的,得改成异步函数来获取并管理token的状态,包括token值和过期时间:

// config.js
import axios from 'axios'

// 存储两个API的token信息,包括token值和过期时间戳
let tokenCache = {
  api1: {
    token: '',
    expireTime: 0
  },
  api2: {
    token: '',
    expireTime: 0
  }
}

// 用于避免并发请求重复刷新token的锁
let isRefreshing = {
  api1: false,
  api2: false
}
// 存储等待重试的请求队列
let requestQueue = {
  api1: [],
  api2: []
}

// 获取api_1的token
async function getApi1Token() {
  const response = await axios.get('url/access_token_1')
  const { access_token_1, expires_in } = response.data
  // 计算过期时间(当前时间 + 有效期,留10秒缓冲避免提前过期)
  tokenCache.api1.token = access_token_1
  tokenCache.api1.expireTime = Date.now() + (expires_in - 10) * 1000
  return access_token_1
}

// 获取api_2的token
async function getApi2Token() {
  const response = await axios.get('url/access_token_2')
  const { access_token_2, expires_in } = response.data
  tokenCache.api2.token = access_token_2
  tokenCache.api2.expireTime = Date.now() + (expires_in - 10) * 1000
  return access_token_2
}

// 判断token是否过期
function isTokenExpired(apiType) {
  return Date.now() > tokenCache[apiType].expireTime || !tokenCache[apiType].token
}

第二步:给Axios实例添加拦截器

接下来给你的Axios实例添加请求拦截器(请求前设置正确的token)和响应拦截器(处理token过期后的重试):

// 继续在config.js里写
export const instance = axios.create({
  // 这里不需要默认设置Authorization,交给拦截器处理
})

// 请求拦截器:根据URL判断API类型,设置对应token
instance.interceptors.request.use(async (config) => {
  let apiType
  // 根据请求URL判断属于哪个API
  if (config.url.includes('/sas/')) {
    apiType = 'api1'
  } else if (config.url.includes('/sps/')) {
    apiType = 'api2'
  }

  if (apiType) {
    // 如果token过期,先刷新token
    if (isTokenExpired(apiType)) {
      // 如果正在刷新当前API的token,把请求加入队列等待
      if (isRefreshing[apiType]) {
        return new Promise((resolve) => {
          requestQueue[apiType].push(() => resolve(config))
        })
      }
      isRefreshing[apiType] = true
      try {
        // 重新获取token
        await (apiType === 'api1' ? getApi1Token() : getApi2Token())
        // 刷新完成后,执行队列里的请求
        requestQueue[apiType].forEach(cb => cb())
        requestQueue[apiType] = []
      } finally {
        isRefreshing[apiType] = false
      }
    }
    // 设置对应API的认证头
    config.headers.Authorization = `Bearer ${tokenCache[apiType].token}`
  }
  return config
}, (error) => {
  return Promise.reject(error)
})

// 响应拦截器:处理接口返回的401(token过期或无效),刷新token后重试请求
instance.interceptors.response.use((response) => {
  return response
}, async (error) => {
  const originalRequest = error.config
  // 判断是否是401错误,且不是已经重试过的请求
  if (error.response?.status === 401 && !originalRequest._retry) {
    originalRequest._retry = true
    let apiType
    if (originalRequest.url.includes('/sas/')) {
      apiType = 'api1'
    } else if (originalRequest.url.includes('/sps/')) {
      apiType = 'api2'
    }

    if (apiType) {
      // 强制刷新token
      await (apiType === 'api1' ? getApi1Token() : getApi2Token())
      // 设置新的token后重试请求
      originalRequest.headers.Authorization = `Bearer ${tokenCache[apiType].token}`
      return instance(originalRequest)
    }
  }
  return Promise.reject(error)
})

第三步:API调用代码无需修改

你原来的API调用代码可以完全保留,拦截器会自动在请求前处理token的过期判断和设置:

//Api_1
export const getCountry = async (country: string) => {
  const response = await instance.get(
    `/sas/${country}`
  )
  return response.data
}

//Api_2
export const getCity = async (city: string) => {
  const response = await instance.get(
    `/sps/${city}`
  )
  return response.data
}

关键逻辑说明

  • token过期判断:通过对比当前时间和预先计算的过期时间戳,提前10秒刷新token避免请求时刚好过期
  • 并发请求处理:用锁变量和请求队列,避免多个请求同时触发token刷新,造成重复请求
  • URL匹配:通过请求URL里的特征路径(/sas/、/sps/)判断属于哪个API,设置对应token
  • 401重试:如果接口返回401,说明token确实失效了,强制刷新后重试原请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:10:19