
本文介绍如何全面捕获网页中的各类网络请求(包括 fetch、xmlhttprequest 及其封装库如 axios),通过重写原生 api 与合理使用拦截器,实现统一的请求监听机制。
本文介绍如何全面捕获网页中的各类网络请求(包括 fetch、xmlhttprequest 及其封装库如 axios),通过重写原生 api 与合理使用拦截器,实现统一的请求监听机制。
在前端开发中,有时需要全局监听网络请求以实现性能监控、调试日志、权限校验或埋点上报等功能。但仅重写 fetch(如使用 Proxy)是不够的——因为许多主流请求库(如 Axios、jQuery.ajax、甚至部分 React Query 或 SWR 的底层调用)默认基于 XMLHttpRequest(XHR),而非 fetch。因此,你观察到 axios 请求未被触发,正是由于它绕过了你重写的 fetch。
要真正实现“监听所有网络请求”,需双管齐下:同时劫持 fetch 和 XMLHttpRequest 原生接口,并对第三方库(如 Axios)提供可选的增强方案。
✅ 方案一:统一劫持原生请求接口(推荐基础方案)
// 1. 拦截 fetch
const originalFetch = window.fetch;
window.fetch = new Proxy(originalFetch, {
apply(target, thisArg, args) {
const [input, init] = args;
const url = typeof input === 'string' ? input : input?.url || '';
// 触发自定义事件或执行逻辑
if (url.includes('/example')) {
console.log('[FETCH] Detected request to /example:', url);
// 可派发 CustomEvent、调用监控 SDK、记录日志等
}
return Reflect.apply(target, thisArg, args)
.then(response => {
// 可选:监听响应完成
console.log('[FETCH] Response received:', response.status, url);
return response;
})
.catch(err => {
console.warn('[FETCH] Request failed:', url, err);
throw err;
});
}
});
// 2. 拦截 XMLHttpRequest
const originalXhr = window.XMLHttpRequest;
window.XMLHttpRequest = function () {
const xhr = new originalXhr();
const { open, send } = xhr;
xhr.open = function (method, url, ...rest) {
// 请求发起前监听
if (url.includes('/example')) {
console.log(`[XHR] ${method} request to:`, url);
}
return open.call(this, method, url, ...rest);
};
xhr.send = function (...args) {
// 可在此注入请求头、添加超时逻辑等
const onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.responseURL?.includes('/example')) {
console.log(`[XHR] Completed: ${xhr.status}`, xhr.responseURL);
}
}
};
if (xhr.addEventListener) {
xhr.addEventListener('readystatechange', onreadystatechange);
} else {
xhr.onreadystatechange = onreadystatechange;
}
return send.call(this, ...args);
};
return xhr;
};⚠️ 注意事项:
- 劫持
XMLHttpRequest时务必保留原始原型链和事件机制,避免破坏依赖 XHR 的库(如旧版 Axios);- 避免在
send中直接return Promise—— XHR 是事件驱动的,需通过onload/onerror或addEventListener处理;- 若页面存在多个脚本动态加载,建议将上述代码置于
中最早执行的<script></script>(或使用document.write注入),确保劫持发生在其他脚本初始化之前。
✅ 方案二:针对 Axios 的增强(补充拦截器)
若项目已大量使用 Axios,且你希望更语义化、可维护地接入监听逻辑,推荐结合其原生拦截器:
import axios from 'axios';
// 全局请求拦截器(发送前)
axios.interceptors.request.use(
config => {
if (config.url?.includes('/example')) {
console.log('[AXIOS REQUEST]', config.method.toUpperCase(), config.url);
// 可附加 traceId、埋点标识、鉴权头等
config.headers['X-Request-Trace'] = Date.now().toString(36);
}
return config;
},
error => Promise.reject(error)
);
// 全局响应拦截器(接收后)
axios.interceptors.response.use(
response => {
if (response.config.url?.includes('/example')) {
console.log('[AXIOS RESPONSE]', response.status, response.config.url);
}
return response;
},
error => {
if (error.config?.url?.includes('/example')) {
console.warn('[AXIOS ERROR]', error.config.url, error.message);
}
return Promise.reject(error);
}
);? 提示:Axios 拦截器是声明式、可复用、支持链式注册的,适合工程化场景;但它无法覆盖非 Axios 发起的请求(如原生
fetch、图片加载、<script></script>标签请求等),因此仍需配合方案一才能做到真正“全量监听”。
✅ 总结与最佳实践
| 方式 | 覆盖范围 | 是否侵入式 | 推荐场景 |
|---|---|---|---|
fetch + XMLHttpRequest 劫持 |
✅ 所有原生请求(含图片、CSS、Script 等资源加载) | 是(需谨慎) | 调试工具、性能监控 SDK、安全审计 |
| Axios 拦截器 | ✅ 仅 Axios 实例发出的请求 | 否(无副作用) | 已深度集成 Axios 的业务系统 |
| 组合使用 | ✅ 全面覆盖 JS 主动发起的网络请求 | ⚠️ 劫持部分需前置注入 | 生产级监控、合规审计、DevTools 扩展 |
最后提醒:在生产环境中启用全局请求监听时,请务必评估性能开销(尤其高频请求场景),避免在拦截逻辑中执行耗时操作;敏感信息(如 token、用户数据)也应脱敏处理,符合隐私合规要求。

















