@bugspotter/sdk
Version:
Professional bug reporting SDK with screenshots, session replay, and automatic error capture for web applications
136 lines (135 loc) • 5.22 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NetworkCapture = void 0;
const base_capture_1 = require("./base-capture");
const circular_buffer_1 = require("../core/circular-buffer");
class NetworkCapture extends base_capture_1.BaseCapture {
constructor(options = {}) {
var _a;
super(options);
this.isIntercepting = false;
const maxRequests = (_a = options.maxRequests) !== null && _a !== void 0 ? _a : 50;
this.buffer = new circular_buffer_1.CircularBuffer(maxRequests);
this.filterUrls = options.filterUrls;
this.originalFetch = window.fetch;
this.originalXHR = {
open: XMLHttpRequest.prototype.open,
send: XMLHttpRequest.prototype.send,
};
this.interceptFetch();
this.interceptXHR();
this.isIntercepting = true;
}
capture() {
return this.getRequests();
}
parseFetchArgs(args) {
const [input, init] = args;
let url;
let method = 'GET';
if (typeof input === 'string') {
url = input;
}
else if (input instanceof Request) {
url = input.url;
method = input.method.toUpperCase() || 'GET';
}
else {
url = input.toString();
}
if (init === null || init === void 0 ? void 0 : init.method) {
method = init.method.toUpperCase();
}
return { url, method };
}
createNetworkRequest(url, method, status, startTime, error) {
const request = Object.assign({ url,
method,
status, duration: Date.now() - startTime, timestamp: startTime }, (error && { error }));
// Sanitize network data if sanitizer is enabled
if (this.sanitizer) {
const sanitized = this.sanitizer.sanitizeNetworkData(Object.assign({ url: request.url, method: request.method, status: request.status }, (request.error && { error: request.error })));
return Object.assign(Object.assign({}, request), { url: sanitized.url || request.url, error: sanitized.error });
}
return request;
}
addRequest(request) {
if (this.filterUrls && !this.filterUrls(request.url)) {
return; // Skip filtered URLs
}
this.buffer.add(request);
}
interceptFetch() {
const originalFetch = this.originalFetch;
window.fetch = async (...args) => {
const startTime = Date.now();
let url = '';
let method = 'GET';
try {
({ url, method } = this.parseFetchArgs(args));
}
catch (error) {
this.handleError('parsing fetch arguments', error);
}
try {
const response = await originalFetch(...args);
const request = this.createNetworkRequest(url, method, response.status, startTime);
this.addRequest(request);
return response;
}
catch (error) {
const request = this.createNetworkRequest(url, method, 0, startTime, error.message);
this.addRequest(request);
throw error;
}
};
}
interceptXHR() {
const originalOpen = this.originalXHR.open;
const originalSend = this.originalXHR.send;
const createRequest = this.createNetworkRequest.bind(this);
const addRequest = this.addRequest.bind(this);
XMLHttpRequest.prototype.open = function (method, url, ...args) {
this._method = method.toUpperCase();
this._url = url.toString();
this._startTime = Date.now();
// Type assertion needed for rest params compatibility
return originalOpen.apply(this, [method, url, ...args]);
};
XMLHttpRequest.prototype.send = function (...args) {
const onLoad = () => {
const request = createRequest(this._url || '', this._method || 'GET', this.status, this._startTime || Date.now());
addRequest(request);
};
const onError = () => {
const request = createRequest(this._url || '', this._method || 'GET', 0, this._startTime || Date.now(), 'XMLHttpRequest failed');
addRequest(request);
};
this.addEventListener('load', onLoad);
this.addEventListener('error', onError);
// Type assertion needed for rest params compatibility
return originalSend.apply(this, args);
};
}
getRequests() {
return this.buffer.getAll();
}
clear() {
this.buffer.clear();
}
destroy() {
if (!this.isIntercepting) {
return;
}
try {
window.fetch = this.originalFetch;
XMLHttpRequest.prototype.open = this.originalXHR.open;
XMLHttpRequest.prototype.send = this.originalXHR.send;
this.isIntercepting = false;
}
catch (error) {
this.handleError('destroying network capture', error);
}
}
}
exports.NetworkCapture = NetworkCapture;