Intercepted XHR - run function before raising load

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-24 19:54:00

问题


On a web page with a extension-injected custom XMLHttpRequest class, I need to intercept and modify certain responses before the load event is raised on the rest of the document. Right now, my modification code reacts to the load event. How would I use a function to modify the response before the load event was fired?

This is the code I am using:

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);
};

This question is a continuation of this previous thread.


回答1:


Override onreadystatechange (fired before load/onload) inside 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();

Since other extensions or page scripts may also hook XHR, it would make sense to run your code in a content script with "run_at": "document_start".



来源:https://stackoverflow.com/questions/55270830/intercepted-xhr-run-function-before-raising-load

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!