UNPKG

@splitsoftware/splitio-commons

Version:
83 lines (82 loc) 4.42 kB
"use strict"; 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;