@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
83 lines (82 loc) • 4.42 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitHttpClientFactory = void 0;
var objectAssign_1 = require("../utils/lang/objectAssign");
var constants_1 = require("../logger/constants");
var decorateHeaders_1 = require("./decorateHeaders");
var timeout_1 = require("../utils/promise/timeout");
var PENDING_FETCH_ERROR_TIMEOUT = 100;
var messageNoFetch = 'Global fetch API is not available.';
/**
* Factory of Split HTTP clients, which are HTTP clients with predefined headers for Split endpoints.
*
* @param settings - SDK settings, used to access authorizationKey, logger instance and metadata (SDK version, ip and hostname) to set additional headers
* @param platform - object containing environment-specific dependencies
*/
function splitHttpClientFactory(settings, _a) {
var getOptions = _a.getOptions, getFetch = _a.getFetch;
var log = settings.log, authorizationKey = settings.core.authorizationKey, version = settings.version, _b = settings.runtime, ip = _b.ip, hostname = _b.hostname;
var options = getOptions && getOptions(settings);
var fetch = getFetch && getFetch(settings);
// if fetch is not available, log Error
if (!fetch)
log.error(constants_1.ERROR_CLIENT_CANNOT_GET_READY, [messageNoFetch]);
var commonHeaders = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': "Bearer " + authorizationKey,
'SplitSDKVersion': version
};
if (ip)
commonHeaders['SplitSDKMachineIP'] = ip;
if (hostname)
commonHeaders['SplitSDKMachineName'] = (0, decorateHeaders_1.removeNonISO88591)(hostname);
return function httpClient(url, reqOpts, latencyTracker, logErrorsAsInfo) {
if (reqOpts === void 0) { reqOpts = {}; }
if (latencyTracker === void 0) { latencyTracker = function () { }; }
if (logErrorsAsInfo === void 0) { logErrorsAsInfo = false; }
var request = (0, objectAssign_1.objectAssign)({
headers: (0, decorateHeaders_1.decorateHeaders)(settings, (0, objectAssign_1.objectAssign)({}, commonHeaders, reqOpts.headers || {})),
method: reqOpts.method || 'GET',
body: reqOpts.body
}, options);
// using `fetch(url, options)` signature to work with unfetch, a lightweight ponyfill of fetch API.
return fetch ? fetch(url, request)
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful
.then(function (response) {
if (!response.ok) {
// timeout since `text()` promise might not settle in some fetch implementations and cases (e.g. no content)
return (0, timeout_1.timeout)(PENDING_FETCH_ERROR_TIMEOUT, response.text()).then(function (message) { return Promise.reject({ response: response, message: message }); }, function () { return Promise.reject({ response: response }); });
}
latencyTracker();
return response;
})
.catch(function (error) {
var resp = error && error.response;
var msg = '';
if (resp) { // An HTTP error
switch (resp.status) {
case 404:
msg = 'Invalid SDK key or resource not found.';
break;
// Don't use resp.statusText since reason phrase is removed in HTTP/2
default:
msg = error.message;
break;
}
}
else { // Something else, either an error making the request or a Network error.
msg = error.message || 'Network Error';
}
if (!resp || resp.status !== 403) { // 403's log we'll be handled somewhere else.
log[logErrorsAsInfo ? 'info' : 'error'](constants_1.ERROR_HTTP, [resp ? 'status code ' + resp.status : 'no status code', url, msg]);
}
var networkError = new Error(msg);
// passes `undefined` as statusCode if not an HTTP error (resp === undefined)
networkError.statusCode = resp && resp.status;
latencyTracker(networkError);
throw networkError;
}) : Promise.reject(new Error(messageNoFetch));
};
}
exports.splitHttpClientFactory = splitHttpClientFactory;
;