UNPKG

@webex/http-core

Version:

Core HTTP library for the Cisco Webex

241 lines (233 loc) • 7.82 kB
/*! * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file. */ // Need to fork xhr to support environments with full object freezing; namely, // SalesForce's Aura and Locker environment. // See https://github.com/naugtur/xhr for license information // Maintain the original code style of https://github.com/naugtur/xhr since // we're trying to diverge as little as possible. /* eslint-disable */ 'use strict'; var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property"); var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify")); var window = require('global/window'); var isFunction = require('is-function'); var parseHeaders = require('parse-headers'); var xtend = require('xtend'); createXHR.XMLHttpRequest = window.XMLHttpRequest || noop; createXHR.XDomainRequest = 'withCredentials' in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window.XDomainRequest; forEachArray(['get', 'put', 'post', 'patch', 'head', 'delete'], function (method) { createXHR[method === 'delete' ? 'del' : method] = function (uri, options, callback) { options = initParams(uri, options, callback); options.method = method.toUpperCase(); return _createXHR(options); }; }); function forEachArray(array, iterator) { for (var i = 0; i < array.length; i += 1) { iterator(array[i]); } } function isEmpty(obj) { for (var i in obj) { if (obj.hasOwnProperty(i)) return false; } return true; } function initParams(uri, options, callback) { var params = uri; if (isFunction(options)) { callback = options; if (typeof uri === 'string') { params = { uri: uri }; } } else { params = xtend(options, { uri: uri }); } params.callback = callback; return params; } function createXHR(uri, options, callback) { options = initParams(uri, options, callback); return _createXHR(options); } function _createXHR(options) { if (typeof options.callback === 'undefined') { throw new Error('callback argument missing'); } var called = false; var callback = function cbOnce(err, response, body) { if (!called) { called = true; options.callback(err, response, body); } }; function readystatechange() { if (xhr.readyState === 4) { setTimeout(loadFunc, 0); } } function getBody() { // Chrome with requestType=blob throws errors arround when even testing access to responseText var body = undefined; if (xhr.response) { body = xhr.response; } else { body = xhr.responseText || getXml(xhr); } if (isJson) { try { body = JSON.parse(body); } catch (e) {} } return body; } function errorFunc(evt) { clearTimeout(timeoutTimer); if (!(evt instanceof Error)) { if (evt instanceof ProgressEvent) { var _evt$target; evt = new Error("XMLHttpRequest Error: ProgressEvent: loaded=".concat(evt.loaded, ", total=").concat(evt.total, ", lengthComputable=").concat(evt.lengthComputable, ", target.readyState=").concat((_evt$target = evt.target) === null || _evt$target === void 0 ? void 0 : _evt$target.readyState)); } else { evt = new Error('' + (evt || 'Unknown XMLHttpRequest Error')); } } evt.statusCode = 0; return callback(evt, failureResponse); } // will load the data & process the response in a special response object function loadFunc() { if (aborted) return; var status; clearTimeout(timeoutTimer); if (options.useXDR && xhr.status === undefined) { //IE8 CORS GET successful response doesn't have a status field, but body is fine status = 200; } else { status = xhr.status === 1223 ? 204 : xhr.status; } var response = failureResponse; var err = null; if (status !== 0) { response = { body: getBody(), statusCode: status, method: method, headers: {}, url: uri, rawRequest: xhr }; if (xhr.getAllResponseHeaders) { //remember xhr can in fact be XDR for CORS in IE response.headers = parseHeaders(xhr.getAllResponseHeaders()); } } else { err = new Error('Internal XMLHttpRequest Error'); } return callback(err, response, response.body); } var xhr = options.xhr || null; if (!xhr) { if (options.cors || options.useXDR) { xhr = new createXHR.XDomainRequest(); } else { xhr = new createXHR.XMLHttpRequest(); } } var key; var aborted; var uri = options.uri || options.url; var method = options.method || 'GET'; var body = options.body || options.data; var headers = options.headers || {}; var sync = !!options.sync; var isJson = false; var timeoutTimer; var failureResponse = { body: undefined, headers: {}, statusCode: 0, method: method, url: uri, rawRequest: xhr }; if ('json' in options && options.json !== false) { isJson = true; headers['accept'] || headers['Accept'] || (headers['Accept'] = 'application/json'); //Don't override existing accept header declared by user if (method !== 'GET' && method !== 'HEAD') { headers['content-type'] || headers['Content-Type'] || (headers['Content-Type'] = 'application/json'); //Don't override existing accept header declared by user body = (0, _stringify.default)(options.json === true ? body : options.json); } } xhr.onreadystatechange = readystatechange; xhr.onload = loadFunc; xhr.onerror = errorFunc; // IE9 must have onprogress be set to a unique function. xhr.onprogress = function () { // IE must die }; xhr.onabort = function () { aborted = true; }; xhr.ontimeout = errorFunc; xhr.open(method, uri, !sync, options.username, options.password); //has to be after open if (!sync) { xhr.withCredentials = !!options.withCredentials; } // Cannot set timeout with sync request // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent if (!sync && options.timeout > 0) { timeoutTimer = setTimeout(function () { if (aborted) return; aborted = true; //IE9 may still call readystatechange xhr.abort('timeout'); var e = new Error('XMLHttpRequest timeout'); e.code = 'ETIMEDOUT'; errorFunc(e); }, options.timeout); } if (xhr.setRequestHeader) { for (key in headers) { if (headers.hasOwnProperty(key)) { xhr.setRequestHeader(key, headers[key]); } } } else if (options.headers && !isEmpty(options.headers)) { throw new Error('Headers cannot be set on an XDomainRequest object'); } if ('responseType' in options) { xhr.responseType = options.responseType; } if ('beforeSend' in options && typeof options.beforeSend === 'function') { options.beforeSend(xhr); } // Microsoft Edge browser sends "undefined" when send is called with undefined value. // XMLHttpRequest spec says to pass null as body to indicate no body // See https://github.com/naugtur/xhr/issues/100. xhr.send(body || null); return xhr; } function getXml(xhr) { if (xhr.responseType === 'document') { return xhr.responseXML; } var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === 'parsererror'; if (xhr.responseType === '' && !firefoxBugTakenEffect) { return xhr.responseXML; } return null; } function noop() {} var _default = exports.default = createXHR; //# sourceMappingURL=xhr.js.map