@webex/http-core
Version:
Core HTTP library for the Cisco Webex
241 lines (233 loc) • 7.82 kB
JavaScript
/*!
* 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 */
;
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