问题
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