@launchdarkly/js-server-sdk-common
Version:
LaunchDarkly Server SDK for JavaScript - common code
69 lines • 3.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const js_sdk_common_1 = require("@launchdarkly/js-sdk-common");
/**
* @internal
*/
class Requestor {
constructor(config, _requests, baseHeaders, _path = '/sdk/latest-all', _logger, serviceEndpointsOverride) {
this._requests = _requests;
this._path = _path;
this._logger = _logger;
this._eTagCache = {};
this._headers = Object.assign({}, baseHeaders);
this._serviceEndpoints = serviceEndpointsOverride !== null && serviceEndpointsOverride !== void 0 ? serviceEndpointsOverride : config.serviceEndpoints;
this._timeoutMs = config.timeout * 1000;
}
/**
* Perform a request and utilize the ETag cache. The ETags are cached in the
* requestor instance.
*/
async _requestWithETagCache(requestUrl, options) {
const cacheEntry = this._eTagCache[requestUrl];
const cachedETag = cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.etag;
const updatedOptions = cachedETag
? Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'if-none-match': cachedETag }) }) : options;
const res = await this._requests.fetch(requestUrl, updatedOptions);
if (res.status === 304 && cacheEntry) {
return { res, body: cacheEntry.body };
}
const etag = res.headers.get('etag');
const body = await res.text();
if (etag) {
this._eTagCache[requestUrl] = { etag, body };
}
return { res, body };
}
async requestAllData(cb, queryParams = []) {
var _a, _b;
const options = {
method: 'GET',
headers: this._headers,
timeout: this._timeoutMs,
};
const uri = (0, js_sdk_common_1.getPollingUri)(this._serviceEndpoints, this._path, queryParams);
(_a = this._logger) === null || _a === void 0 ? void 0 : _a.debug(`Requestor making request to uri: ${uri}`);
try {
const { res, body } = await this._requestWithETagCache(uri, options);
(_b = this._logger) === null || _b === void 0 ? void 0 : _b.debug(`Requestor got (possibly cached) body: ${JSON.stringify(body)}`);
// Per the FDv2 spec, x-ld-fd-fallback signals that the SDK should switch to FDv1
// for the remainder of the lifetime. The signal can ride along on either a successful
// response or an error response -- in both cases callers must apply any accompanying
// payload before honoring the directive.
const fallbackToFDv1 = res.headers.get(`x-ld-fd-fallback`) === `true`;
const responseHeaders = Object.fromEntries(res.headers.entries());
if (res.status !== 200 && res.status !== 304) {
const err = fallbackToFDv1
? new js_sdk_common_1.LDFlagDeliveryFallbackError(js_sdk_common_1.DataSourceErrorKind.ErrorResponse, `Response header indicates to fallback to FDv1.`, res.status)
: new js_sdk_common_1.LDPollingError(js_sdk_common_1.DataSourceErrorKind.ErrorResponse, `Unexpected status code: ${res.status}`, res.status);
return cb(err, undefined, responseHeaders, fallbackToFDv1);
}
return cb(undefined, res.status === 304 ? null : body, responseHeaders, fallbackToFDv1);
}
catch (err) {
return cb(err, undefined, undefined, false);
}
}
}
exports.default = Requestor;
//# sourceMappingURL=Requestor.js.map