如何正确重写XmlHttpRequest以在请求头中传递自定义键值对
自动为XMLHttpRequest添加自定义请求头的原生JS实现
你的思路方向是对的——通过重写XMLHttpRequest的原型方法来全局注入请求头,但原代码里有几个关键问题会导致功能失效,我来帮你修正并解释清楚:
原代码的核心问题
- send方法丢失原生发送逻辑:你重写了send方法,但完全没调用原生的send,导致请求根本发不出去
- setRequestHeader调用错误:直接用
xhrProto.setRequestHeader会导致上下文混乱,应该用当前请求实例的this来调用 - token获取时机不合理:在
override初始化时就获取token,如果后续localStorage里的token更新了,新请求还是会用旧值
修正后的完整实现
class OverrideXMLHttpRequest { static override() { // 保存原生的open和send方法 const originalOpen = XMLHttpRequest.prototype.open; const originalSend = XMLHttpRequest.prototype.send; // 重写open方法,可选择保存请求信息(不影响核心功能,仅做扩展) XMLHttpRequest.prototype.open = function(method, url) { this._requestMethod = method; this._requestUrl = url; return originalOpen.apply(this, arguments); }; // 重写send方法,注入请求头并执行原生发送逻辑 XMLHttpRequest.prototype.send = function(body) { // 每次发送请求时获取最新的token,适配token更新场景 const userToken = localStorage.getItem('userToken'); if (userToken) { // 必须用当前实例调用setRequestHeader,且时机在open之后、send之前 this.setRequestHeader('UserToken', userToken); } // 调用原生send方法,传递请求体参数 return originalSend.apply(this, arguments); }; } } export default OverrideXMLHttpRequest;
关键细节说明
- 绑定实例上下文:所有操作都基于当前XHR实例的
this,确保每个请求独立处理,不会互相干扰 - 实时获取token:每次发送请求时重新从localStorage取值,保证用的是最新的用户token
- 保留原生功能:必须通过
apply调用原生的open和send方法,确保XMLHttpRequest的原有行为不受破坏 - 兼容性友好:这个实现兼容所有支持ES6类和XMLHttpRequest的现代浏览器,完全不需要依赖第三方库
使用时只需要在项目初始化的地方调用一次OverrideXMLHttpRequest.override(),之后所有通过原生XMLHttpRequest发送的请求,只要localStorage里存在userToken,就会自动带上UserToken请求头。
内容的提问来源于stack exchange,提问作者Hugo




