In this post we will review how to capture the JavaScript XMLHttpRequest API calls. This is required if you want to modify all the requests sent by the XMLHttpRequest object in the HTML page (e.g. add headers), or just log something from the requests.
The XMLHttpRequest includes open method, and a send method. We start by keeping references to the original implementations:
const origOpen = window.XMLHttpRequest.prototype.open
const origSend = window.XMLHttpRequest.prototype.send
Next, we update the open implementation, to keep the url that is being accessed:
XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
this._url = url
origOpen.apply(this, arguments)
}
Once the send method is called, we can log the URL and the body. We can also add headers in this step.
XMLHttpRequest.prototype.send = function () {
if (this.onreadystatechange) {
this._onreadystatechange = this.onreadystatechange
}
this.onreadystatechange = onReadyStateChangeReplacement
console.log(`sending url ${this._url} body:`, arguments[0])
this.setRequestHeader('my-header', 'my-value')
actualSend()
async function actualSend() {
origSend.apply(this, arguments)
}
function onReadyStateChangeReplacement() {
if (this._onreadystatechange) {
return this._onreadystatechange.apply(this, arguments)
}
}
}
Notice the special handling for the onreadystatechange, in goal to use the correct "this" object.
Once this is done, any use of XMLHttpObject in the page will print to console log the url and the body, and also will add a custom header to the request.