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

Axios拦截器重复拼接URL问题技术求助

Axios请求URL重复叠加的问题解决方法

嘿,这个问题我太熟了!根源就在你的请求拦截器里——每次请求都会把API基础URL拼接到config.url上,但拦截器是全局生效的,第二次请求时config.url已经是拼接好的完整URL,再拼一次就会导致重复叠加,这就是你看到URL变成http://localhost:3001/http://localhost:3001/...的原因。

问题代码分析

你在拦截器里写了这行关键代码:

config.url = `${process.env.REACT_APP_API_URL}/${config.url}`;

第一次请求时,config.url是user/5e4844f6451e0078e7dd398e,拼接后得到完整URL没问题;但第二次请求时,config.url已经是上一次处理后的http://localhost:3001/user/...,再拼一次基础URL就会重复嵌套,自然就出错了。

正确解决方案(推荐方案:使用Axios实例设置baseURL)

这是Axios官方推荐的做法,既规范又能从根源避免这类问题:

  1. 创建专属Axios实例并配置基础URL
import axios from "axios";

// 创建API请求实例,预设baseURL和默认请求头
const apiClient = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
  headers: {
    'Content-Type': 'application/json'
  }
});

// 给实例添加请求拦截器
apiClient.interceptors.request.use(function (config) {
  const token = localStorage.getItem(process.env.REACT_APP_TOKEN_NAME);
  // 仅当存在token时才设置Authorization头,避免空token无效请求
  if (token) {
    config.headers.common['authorization'] = `Bearer ${token}`;
  }
  console.log(config.url); // 这里只会打印`user/${id}`,baseURL会自动完成拼接
  return config;
}, function (error) {
  return Promise.reject(error);
});

export default apiClient;
  1. 使用该实例发起请求
// 导入刚才创建的apiClient实例
import apiClient from './path-to-your-api-client-file';

export const getUserDetailsById = async ({id}) => {
  const res = await apiClient.get(`user/${id}`);
  return res.data;
};

备选方案:在拦截器里判断URL是否已拼接

如果你不想创建实例,非要用全局Axios,可以在拼接前检查URL是否为绝对路径,避免重复操作:

import axios from "axios";

export default () => {
  axios.interceptors.request.use(function (config) {
    const token = localStorage.getItem(process.env.REACT_APP_TOKEN_NAME);
    config.headers.common['authorization'] = `Bearer ${token}`;
    config.headers.common['Content-Type'] = 'application/json';
    
    // 仅当URL不是http/https开头的绝对路径时,才拼接基础URL
    if (!/^https?:\/\//.test(config.url)) {
      config.url = `${process.env.REACT_APP_API_URL}/${config.url}`;
    }
    
    console.log(config.url);
    return config;
  }, function (error) {
    return Promise.reject(error);
  });
  
  // 响应拦截器保留原有逻辑即可
  axios.interceptors.response.use(function (response) {
    return response;
  }, function (error) {
    return Promise.reject(error);
  });
};

不过还是强烈推荐第一种方案,因为它更符合Axios的设计逻辑,后续维护和扩展不同API请求也更灵活。

内容的提问来源于stack exchange,提问作者Nir Berko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:57:28