生产中的 Axios 拦截器问题

Axios interceptor issue in production

我在开发应用程序和尝试使用刷新令牌时遇到问题。我正在使用 ADFS 进行身份验证,在那里我得到一个每小时过期的 id_token 和一个持续 8 小时的刷新令牌。

在开发过程中,下面的脚本可以完美地按预期工作,并且可以连接到服务器进行刷新。

在生产环境中,它获得了新的令牌,但它从不重试原始请求。我试图找出为什么它在 webpack-dev-server 和生产环境中不同。

如有任何帮助,我们将不胜感激!

P.S。使用 Babel 预设:babel-preset-env 和 babel-preset-stage-2

axios.js

import axios from 'axios'

// Set baseURL for development and production
const baseURL = process.env.NODE_ENV === 'development' ? '//localhost:3001/api' : '/api'

// Create instance of axios with correct baseURL
const instance = axios.create({
  baseURL
})

// Intercept responses
instance.interceptors.response.use((response) => {
  return response
}, async (error) => {

  // Pull config, status and data from the error
  const { config, response: { status, data } } = error

  // Pull tokens from local storage
  let currentTokens = JSON.parse(localStorage.getItem('tokens')) || null

  // If response errors at 401, token is still valid and we have tokens in localStorage
  if(status === 401 && data.token_invalid === undefined && currentTokens && !config._retry) {
    config._retry = true

    try {
      // Ask server for new token
      const authenticate = await instance.post('/user/login', {refresh_token: currentTokens.refresh_token})

      // Pull tokens and success from authenticated request
      const { tokens, success } = authenticate.data

      // If successful, set access_token, id_token, headers and localStorage      
      if(success) {
        currentTokens.access_token = tokens.access_token
        currentTokens.id_token = tokens.id_token

        const bearer = `Bearer ${tokens.id_token}`
        config.headers['Authorization'] = bearer
        Object.assign(instance.defaults, {headers: {Authorization: bearer}})

        localStorage.setItem('tokens', JSON.stringify(currentTokens))

        // Rerun original request
        return instance(config)
      }
    } catch (e) {
      // Catch any errors
      console.log(e)
      return
    }
  } else if(data && data.token_invalid !== undefined && data.token_invalid) {
    // If refresh has expired, take user to ADFS to reauthenticate
    location = `${process.env.OAUTH_CLIENT_EP}?client_id=${process.env.AZURE_CLIENT_ID}&redirect_uri=${process.env.REDIRECT_URI}&resource=${process.env.REDIRECT_URI}&response_type=code`
    return
  } else {
    // Console log all remaining errors
    return
  }
})

export default instance

发现问题。看来,因为我同时使用相对和绝对 urls 作为基础 URL,开发中的绝对 URL 被正确处理,但是相对 URL 是被链接到原始请求。

换句话说,在生产中发送,url 看起来像:/api/api/actual/request,它应该只是 /api/actual/request。

我通过在我的配置文件中添加 API_URL 来解决这个问题,并为开发和生产输入绝对 url 并将我的实例创建更新为以下内容。

const instance = axios.create({
  baseURL: process.env.API_URL
})

感谢所有查看并试图提供帮助的人。祝大家有个愉快的一天!