UNPKG

rollbar

Version:

Effortlessly track and debug errors in your JavaScript applications with Rollbar. This package includes advanced error tracking features and an intuitive interface to help you identify and fix issues more quickly.

194 lines (177 loc) 6.01 kB
/*global XDomainRequest*/ import logger from '../../logger.js'; import * as _ from '../../utility.js'; function makeXhrRequest({ accessToken, url, method, payload, headers, callback, requestFactory, timeout, }) { var request; if (requestFactory) { request = requestFactory(); } else { request = _createXMLHTTPObject(); } if (!request) { // Give up, no way to send requests return callback(new Error('No way to send a request')); } try { try { var onreadystatechange = function () { try { if (onreadystatechange && request.readyState === 4) { onreadystatechange = undefined; var parseResponse = _.jsonParse(request.responseText); if (_isSuccess(request)) { const isItemRoute = url.endsWith('/api/1/item/'); const headers = isItemRoute ? { 'Rollbar-Replay-Enabled': request.getResponseHeader( 'Rollbar-Replay-Enabled', ), 'Rollbar-Replay-RateLimit-Remaining': request.getResponseHeader( 'Rollbar-Replay-RateLimit-Remaining', ), 'Rollbar-Replay-RateLimit-Reset': request.getResponseHeader( 'Rollbar-Replay-RateLimit-Reset', ), } : {}; callback(parseResponse.error, parseResponse.value, headers); return; } else if (_isNormalFailure(request)) { if (request.status === 403) { // likely caused by using a server access token var message = parseResponse.value && parseResponse.value.message; logger.error(message); } // return valid http status codes callback(new Error(String(request.status))); } else { // IE will return a status 12000+ on some sort of connection failure, // so we return a blank error // http://msdn.microsoft.com/en-us/library/aa383770%28VS.85%29.aspx var msg = 'XHR response had no status code (likely connection failure)'; callback(_newRetriableError(msg)); } } } catch (ex) { //jquery source mentions firefox may error out while accessing the //request members if there is a network error //https://github.com/jquery/jquery/blob/a938d7b1282fc0e5c52502c225ae8f0cef219f0a/src/ajax/xhr.js#L111 var exc; if (ex && ex.stack) { exc = ex; } else { exc = new Error(ex); } callback(exc); } }; request.open(method, url, true); if (request.setRequestHeader) { request.setRequestHeader('Content-Type', 'application/json'); request.setRequestHeader('X-Rollbar-Access-Token', accessToken); for (const [h, v] of Object.entries(headers ?? {})) { request.setRequestHeader(h, v); } } if (_.isFiniteNumber(timeout)) { request.timeout = timeout; } request.onreadystatechange = onreadystatechange; request.send(payload); } catch (_e1) { // Sending using the normal xmlhttprequest object didn't work, try XDomainRequest if (typeof XDomainRequest !== 'undefined') { // Assume we are in a really old browser which has a bunch of limitations: // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx // Extreme paranoia: if we have XDomainRequest then we have a window, but just in case if (!window || !window.location) { return callback( new Error( 'No window available during request, unknown environment', ), ); } // If the current page is http, try and send over http if ( window.location.href.substring(0, 5) === 'http:' && url.substring(0, 5) === 'https' ) { url = 'http' + url.substring(5); } var xdomainrequest = new XDomainRequest(); xdomainrequest.onprogress = () => {}; xdomainrequest.ontimeout = function () { var msg = 'Request timed out'; var code = 'ETIMEDOUT'; callback(_newRetriableError(msg, code)); }; xdomainrequest.onerror = function () { callback(new Error('Error during request')); }; xdomainrequest.onload = function () { var parseResponse = _.jsonParse(xdomainrequest.responseText); callback(parseResponse.error, parseResponse.value); }; xdomainrequest.open(method, url, true); xdomainrequest.send(payload); } else { callback(new Error('Cannot find a method to transport a request')); } } } catch (e2) { callback(e2); } } function _createXMLHTTPObject() { /* global ActiveXObject:false */ var factories = [ function () { return new XMLHttpRequest(); }, function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, function () { return new ActiveXObject('Msxml3.XMLHTTP'); }, function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, ]; var xmlhttp; var i; var numFactories = factories.length; for (i = 0; i < numFactories; i++) { try { xmlhttp = factories[i](); break; } catch (_e) { // pass } } return xmlhttp; } function _isSuccess(r) { return r && r.status && r.status === 200; } function _isNormalFailure(r) { return r && _.isType(r.status, 'number') && r.status >= 400 && r.status < 600; } function _newRetriableError(message, code) { var err = new Error(message); err.code = code || 'ENOTFOUND'; return err; } export default makeXhrRequest;