首页 > 解决方案 > 拦截 XHR - 在提高负载之前运行功能

问题描述

在带有扩展注入自定义XMLHttpRequest类的网页上,我需要在文档的其余部分引发事件之前拦截和修改某些响应load现在,我的修改代码对加载事件做出反应。load在触发事件之前,我将如何使用函数来修改响应?

这是我正在使用的代码:

let oldXHROpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
    var originalresp = this;
    //Do something with the method, url and etc.
    originalresp.addEventListener('load', async function () {
        //Do something with the response text
        //***This function needs to execute before load is raised for the rest of the document***
        value = '<note><body>This is a test XML document.</body></note>';
        parser = new DOMParser();
        apiresponsexml = parser.parseFromString(value, 'application/xml');
        //Replace data in the response
        Object.defineProperties(originalresp, {
            'response': {
                value: value
            },
            'responseXML': {
                value: apiresponsexml,
            },
            'responseText': {
                value: value,
            }
        });
    });
    return oldXHROpen.apply(originalresp, arguments);
};

这个问题是这个先前线程的延续。

标签: javascripthtmlgoogle-chrome-extensionxmlhttprequest

解决方案


内部覆盖onreadystatechange(在加载/加载之前触发)send()

function plantXhrHook() {
  let origStateChange;

  function modifyResponse(e) {
    if (this.readyState === 4) {
      const value = 'foo';
      let xml;
      Object.defineProperties(this, {
        response: {value},
        responseText: {value},
        responseXML: {
          get() {
            if (typeof xml === 'undefined')
              xml = new DOMParser().parseFromString(value, 'application/xml');
            return xml;
          },
        },
      });
    }
    if (origStateChange) {
      origStateChange.apply(this, arguments);
    }
  };

  const origSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.send = function () {
    origStateChange = this.onreadystatechange;
    this.onreadystatechange = modifyResponse;
    origSend.apply(this, arguments);
  };
}

const script = document.createElement('script');
script.textContent = `(${plantXhrHook})()`;
document.documentElement.appendChild(script);
script.remove();

由于其他扩展或页面脚本也可能挂钩 XHR,因此使用"run_at": "document_start"在内容脚本中运行您的代码是有意义的。


推荐阅读