You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何正确重写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

火山引擎 最新活动