Skip to content

Instantly share code, notes, and snippets.

@ucjonathan
Created April 29, 2021 13:01
Show Gist options
  • Save ucjonathan/9adc68ee74b331f6da5e0a13e1652dac to your computer and use it in GitHub Desktop.
Save ucjonathan/9adc68ee74b331f6da5e0a13e1652dac to your computer and use it in GitHub Desktop.
XHR Logging
(function(options) {
// Init options if not specified
options = options || {
"capturePayload": false
};
// Store a reference to the native method
let oldOpen = XMLHttpRequest.prototype.open;
var xhrlogcounter = 1;
// Overwrite the native method
XMLHttpRequest.prototype.open = function() {
var that = this;
that.xhrlog = {
method: null,
url: null,
requestHeaders: {},
requestBody: null,
responseHeaders: {},
responseBody: null,
status: null,
statusText: null,
xhrlogcounter: "xhrlog" + xhrlogcounter,
performance: null,
payloadsCaptured: options.capturePayload || false
}
xhrlogcounter++;
that.xhrlog.method = arguments[0];
that.xhrlog.url = arguments[1];
// Capture headers set
var oldSetRequestHeader = that.setRequestHeader;
that.setRequestHeader = function() {
that.xhrlog.requestHeaders[arguments[0]] = arguments[1];
oldSetRequestHeader.apply(this, arguments);
};
// Capture what is sent up
var oldSend = that.send;
that.send = function() {
if (arguments.length && options.capturePayload) {
that.xhrlog.requestBody = arguments[0];
}
// Set a mark before we trigger the XHR so we can find the performance data easier
window.performance.mark(that.xhrlog.xhrlogcounter);
oldSend.apply(this, arguments);
}
// Assign an event listener
this.addEventListener("load", function(event) {
if (options.capturePayload) {
that.xhrlog.responseBody = that.response;
}
}, false);
this.addEventListener("loadend", function(event) {
// Get the raw header string
var headers = that.getAllResponseHeaders();
// Convert the header string into an array
// of individual headers
var arr = headers.trim().split(/[\r\n]+/);
// Create a map of header names to values
arr.forEach(function(line) {
var parts = line.split(': ');
var header = parts.shift();
var value = parts.join(': ');
that.xhrlog.responseHeaders[header] = value;
});
that.xhrlog.status = that.status;
that.xhrlog.statusText = that.statusText;
var entries = window.performance.getEntries();
var markIndex = -1;
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
if (entry.name === that.xhrlog.xhrlogcounter) {
markIndex = i;
break;
}
}
if (markIndex >= 0) {
for (var i = markIndex; i < entries.length; i++) {
var entry = entries[i];
// console.log("checking", entry);
if (entry.initiatorType === "xmlhttprequest" && entry.name && entry.name.indexOf(that.xhrlog.url) >= 0) {
that.xhrlog.performance = entry;
break;
}
}
}
window.performance.clearMarks(that.xhrlog.xhrlogcounter);
// Opportunity to redact anything on the record
if (options.redactFunction) {
options.redactFunction(that.xhrlog);
}
// Opportunity to suppress
if (options.suppressFunction) {
if (options.suppressFunction(that.xhrlog)) return;
}
// Fire an event with this XHR capture
const xhrevent = new CustomEvent('xhrlog', {
detail: that.xhrlog
});
document.dispatchEvent(xhrevent);
}, false);
// Call the stored reference to the native method
oldOpen.apply(this, arguments);
};
})();
// Sample listener to collect the xhrlog records
document.addEventListener('xhrlog', function(event) {
console.log("xhrlog", JSON.stringify(event.detail, null, 2));
}, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment