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官方推荐的做法,既规范又能从根源避免这类问题:
- 创建专属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;
- 使用该实例发起请求
// 导入刚才创建的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
相关产品推荐
相关产品推荐

