悠悠楠杉
深入解析JavaScript网络请求拦截技术
深入解析JavaScript网络请求拦截技术
一、理解网络请求拦截的核心逻辑
在现代Web开发中,网络请求拦截已成为提升应用安全性和用户体验的关键技术。通过拦截HTTP请求,开发者能够实现以下核心功能:
- 请求预处理:在请求发出前修改URL、headers或body数据
- 响应后处理:对返回数据进行统一格式化或错误处理
- 缓存控制:实现自定义缓存策略减少重复请求
- 认证管理:自动添加身份验证令牌
javascript
// 基础拦截示例
const originalFetch = window.fetch;
window.fetch = async function(...args) {
// 请求前处理
console.log('拦截到请求:', args[0]);
// 添加统一headers
const newArgs = [...args];
const options = newArgs[1] || {};
options.headers = {
...options.headers,
'X-Request-ID': generateUUID()
};
try {
const response = await originalFetch.apply(this, newArgs);
// 响应后处理
if(!response.ok) throw new Error('网络异常');
return response;
} catch (error) {
// 统一错误处理
console.error('请求失败:', error);
throw error;
}
}
二、主流实现方案对比
1. Service Worker方案
适用于PWA应用,可离线拦截:
javascript
// service-worker.js
self.addEventListener('fetch', event => {
if(event.request.url.includes('/api/')) {
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetchWithLogging(event.request))
);
}
});
2. Axios拦截器
适合React/Vue项目:
javascript
axios.interceptors.request.use(config => {
config.metadata = { startTime: Date.now() };
return config;
});
axios.interceptors.response.use(
response => {
console.log(耗时: ${Date.now() - response.config.metadata.startTime}ms
);
return response.data;
},
error => {
alert(请求错误: ${error.response?.status || '网络断开'}
);
return Promise.reject(error);
}
);
3. XMLHttpRequest重写
兼容传统项目:
javascript
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
this.addEventListener('load', function() {
if(this.status.toString().startsWith('2')) {
console.log('API调用成功:', url);
}
});
originalOpen.apply(this, arguments);
};
三、实战中的高级技巧
1. 请求节流控制
防止接口洪水攻击:
javascript
const apiQueue = new Map();
window.fetch = new Proxy(window.fetch, {
apply(target, thisArg, args) {
const [url] = args;
if(apiQueue.has(url)) return apiQueue.get(url);
const promise = target.apply(thisArg, args).finally(() => {
apiQueue.delete(url);
});
apiQueue.set(url, promise);
return promise;
}
});
2. 敏感数据过滤
拦截响应中的敏感信息:
javascript
const sensitiveFields = ['password', 'token'];
const sanitizeResponse = async response => {
const clone = response.clone();
const data = await clone.json();
sensitiveFields.forEach(field => {
if(data[field]) data[field] = '******';
});
return new Response(JSON.stringify(data), {
status: response.status,
headers: response.headers
});
};
3. 性能监控集成
收集请求指标数据:
javascript
const analytics = {
track: (metric, value) => {
navigator.sendBeacon('/analytics', JSON.stringify({metric, value}));
}
};
window.fetch = async function(...args) {
const start = performance.now();
const res = await originalFetch(...args);
const duration = performance.now() - start;
analytics.track('api_timing', {
url: args[0],
duration: duration.toFixed(2),
status: res.status
});
return res;
};
四、安全防护实践
CSRF防御:自动添加token到mutating请求
javascript document.cookie = 'XSRF-TOKEN=' + crypto.randomUUID(); axios.defaults.headers.post['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
请求签名验证:javascript
const signRequest = (config) => {
const timestamp = Date.now();
const nonce = Math.random().toString(36).substring(2);
const sign = crypto.createHmac('sha256', SECRET_KEY)
.update(${config.method}${config.url}${timestamp}${nonce}
)
.digest('hex');config.headers['X-Signature'] = sign;
config.headers['X-Timestamp'] = timestamp;
config.headers['X-Nonce'] = nonce;
};DDOS防护:javascript
const requestHistory = [];
axios.interceptors.request.use(config => {
const now = Date.now();
requestHistory.push(now);// 清理10秒前的记录
const threshold = now - 10000;
while(requestHistory[0] < threshold) {
requestHistory.shift();
}if(requestHistory.length > 30) {
return Promise.reject(new Error('请求过于频繁'));
}return config;
});
五、调试与问题排查
日志记录策略:
javascript const debug = { log: (level, ...args) => { if(process.env.NODE_ENV === 'development') { console[level](`[${new Date().toISOString()}]`, ...args); } } };
错误分类处理:
javascript const handleError = error => { if(error.message.includes('Network Error')) { showToast('网络连接异常,请检查网络设置'); } else if(error.response?.status === 401) { redirectToLogin(); } else { reportError(error); } };
请求重试机制:
javascript const fetchWithRetry = async (url, options = {}, retries = 3) => { try { return await fetch(url, options); } catch (err) { if(retries <= 0) throw err; await new Promise(r => setTimeout(r, 1000 * (4 - retries))); return fetchWithRetry(url, options, retries - 1); } };
通过合理运用这些技术方案,开发者可以构建出健壮、安全的前端网络请求体系,大幅提升Web应用的质量和用户体验。