UNPKG

@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
"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;