@noggin/elastic-noggin-sdk
Version:
Elastic Noggin SDK
226 lines (225 loc) • 10.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateRequestOptions = exports.send = void 0;
const Eno_1 = require("./models/Eno");
const rxjs_1 = require("rxjs");
const got_1 = __importDefault(require("got"));
const sessionTokenCache_1 = require("./sessionTokenCache");
const lodash_1 = require("lodash");
const jwt_decode_1 = __importDefault(require("jwt-decode"));
const operators_1 = require("rxjs/operators");
const https_1 = require("https");
const http_1 = require("http");
const SessionTokenHeader = "session-token";
const THIN_OPERATIONS = ["op/pull", "op/formula", "op/query"];
const SessionIdHeader = "Session-Id";
const httpAgent = new http_1.Agent({ keepAlive: true });
const httpsAgent = new https_1.Agent({ keepAlive: true });
const retryIfFasterThanMs = 5000;
function send(batch, options, queryOptions) {
var _a;
const requestOptions = {
json: batch,
responseType: "text",
resolveBodyOnly: false,
throwHttpErrors: false,
headers: {
"Content-type": ["application/json"],
"Conn-Isolation": ["true"],
"User-Agent": "ElasticNogginSDK",
},
agent: {
http: httpAgent,
https: httpsAgent,
},
retry: {
methods: ['GET', 'POST'],
limit: 2,
},
hooks: {
beforeRetry: [
(error, retryCount) => {
var _a, _b;
const elapsedMs = ((_a = retryCount.timings) === null || _a === void 0 ? void 0 : _a.end) - ((_b = retryCount.timings) === null || _b === void 0 ? void 0 : _b.start);
if (isNaN(elapsedMs) || elapsedMs < retryIfFasterThanMs) {
console.warn('[ElasticNogginSDK/Send] Retrying failed request', Object.assign(Object.assign({ elapsedMs }, retryCount), { namespace: options.namespace }));
}
else {
console.warn('[ElasticNogginSDK/Send] Not retrying failed request', Object.assign(Object.assign({ elapsedMs }, retryCount), { namespace: options.namespace }));
throw new Error('Send failed');
}
}
]
}
};
if (options.clientIp) {
(0, lodash_1.set)(requestOptions, ["headers", "encloud-clientip"], [options.clientIp]);
}
if (options.clientVia) {
(0, lodash_1.set)(requestOptions, ["headers", "encloud-via"], [options.clientVia]);
}
if (options.bulk) {
(0, lodash_1.set)(requestOptions, ["headers", "encloud-bulk"], ["true"]);
}
if (options.sessionToken) {
requestOptions.headers[SessionTokenHeader] = options.sessionToken;
}
else if (options.useSharedAnonymousSession && (0, sessionTokenCache_1.hasToken)(options.namespace)) {
requestOptions.headers[SessionTokenHeader] = (0, sessionTokenCache_1.getToken)(options.namespace);
}
if (options.useCurrentSession !== false) {
try {
requestOptions.headers[SessionIdHeader] = getSessionId(options.sessionToken);
}
catch (err) {
}
}
if (requestOptions.headers[SessionTokenHeader] && options.maintainInitialSessionToken && !options.initialSessionToken) {
let sessionToken = requestOptions.headers[SessionTokenHeader];
if ((0, lodash_1.isArray)(sessionToken)) {
sessionToken = sessionToken[0];
}
options.initialSessionToken = sessionToken;
}
if (options.additionalHeaders) {
(0, lodash_1.each)(options.additionalHeaders, (value, key) => (0, lodash_1.set)(requestOptions, ["headers", key], value));
}
updateRequestOptions(batch, options, requestOptions);
if (options.additionalQueryString) {
(0, lodash_1.each)(options.additionalQueryString, (value, key) => (requestOptions.url += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(value)));
}
if ((_a = options.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
if (options.debug) {
console.debug("[ElasticNogginSDK/Send] Already aborted", {
url: requestOptions.url,
requestHeaders: (0, lodash_1.omit)((0, lodash_1.get)(requestOptions, "headers"), [SessionTokenHeader, 'Authorization']),
namespace: options.namespace
});
}
return (0, rxjs_1.throwError)(() => new Error('Request aborted'));
}
const postPromise = got_1.default.post(requestOptions);
let subscriberCount = 0;
const post$ = new rxjs_1.Observable(observer => {
subscriberCount++;
if (options.abortController) {
options.abortController.signal.addEventListener('abort', (err) => {
postPromise.cancel();
if (options.debug) {
console.debug("[ElasticNogginSDK/Send] Abort signal", {
url: requestOptions.url,
requestHeaders: (0, lodash_1.omit)((0, lodash_1.get)(requestOptions, "headers"), [SessionTokenHeader, 'Authorization']),
namespace: options.namespace,
});
}
observer.error(new Error('Request aborted'));
});
}
let isDone = false;
postPromise.then(response => {
isDone = true;
observer.next(response);
observer.complete();
}).catch(err => {
observer.error(err);
});
return () => {
subscriberCount--;
if (subscriberCount === 0 && !isDone && !postPromise.isCanceled) {
if (options.debug) {
console.debug("[ElasticNogginSDK/Send] All unsubscribed before response", {
url: requestOptions.url,
requestHeaders: (0, lodash_1.omit)((0, lodash_1.get)(requestOptions, "headers"), [SessionTokenHeader, 'Authorization']),
namespace: options.namespace,
});
}
postPromise.cancel();
}
};
});
return post$.pipe((0, operators_1.tap)((response) => {
if (options.debug) {
console.debug("[ElasticNogginSDK/Send] Response", {
url: requestOptions.url,
requestHeaders: (0, lodash_1.omit)((0, lodash_1.get)(requestOptions, "headers"), [SessionTokenHeader, 'Authorization']),
responseHeaders: (0, lodash_1.omit)((0, lodash_1.get)(response, "headers"), [SessionTokenHeader, 'Authorization']),
time: (0, lodash_1.pick)(response, [
"elapsedTime",
"timingStart",
"timings",
"timingPhases",
]),
namespace: options.namespace,
statusCode: (0, lodash_1.get)(response, "statusCode"),
requestBodySize: (0, lodash_1.size)(requestOptions.body),
responseBodySize: (0, lodash_1.size)(requestOptions.body),
});
}
}), (0, operators_1.map)((response) => {
if (response.statusCode == 200) {
if (queryOptions) {
const responseHeadersValues = (0, lodash_1.reduce)(queryOptions.responseHeadersToInclude, (headerValues, currentHeader) => {
if (!headerValues) {
headerValues = [];
}
const currentHeaderValue = {
[currentHeader]: (0, lodash_1.get)(response, ["headers", currentHeader], null),
};
headerValues.push(currentHeaderValue);
return headerValues;
}, null);
queryOptions.responseHeadersToInclude = responseHeadersValues;
}
let newSessionToken = response.headers[SessionTokenHeader];
if ((0, lodash_1.isArray)(newSessionToken)) {
newSessionToken = newSessionToken[0];
}
if (newSessionToken) {
if (options.maintainInitialSessionToken && !options.initialSessionToken) {
options.initialSessionToken = newSessionToken;
}
if (options.useSharedAnonymousSession) {
(0, sessionTokenCache_1.setToken)(options.namespace, newSessionToken);
}
else {
options.sessionToken = newSessionToken;
}
}
const parsedBody = JSON.parse(response.body);
return parsedBody.map((obj) => new Eno_1.Eno(obj));
}
else {
throw { message: response.body, code: response.statusCode };
}
}));
}
exports.send = send;
function updateRequestOptions(batch, options, requestOptions) {
if (batch.length === 1) {
const type = batch[0].getType();
if (options.useQueryService && type === 'op/query') {
requestOptions.url = options.enSrvUrl.replace(/\/ensrv\/+$/, "/query/ensrv");
const sessionToken = (0, lodash_1.get)(requestOptions, ['headers', SessionTokenHeader]);
if (sessionToken) {
(0, lodash_1.set)(requestOptions, ['headers', 'Authorization'], 'Bearer ' + sessionToken);
(0, lodash_1.unset)(requestOptions, ['headers', SessionTokenHeader]);
(0, lodash_1.unset)(requestOptions, ['headers', SessionIdHeader]);
}
(0, lodash_1.set)(requestOptions, ['headers', 'en-namespace'], options.namespace);
return;
}
if (THIN_OPERATIONS.indexOf(type) > -1) {
requestOptions.url = options.enSrvUrl.replace(/\/+$/, "") + "/" + type + "?ns=" + encodeURIComponent(options.namespace);
return;
}
}
requestOptions.url = options.enSrvUrl + "?ns=" + encodeURIComponent(options.namespace);
}
exports.updateRequestOptions = updateRequestOptions;
function getSessionId(sessionToken) {
const tokenPayload = (0, jwt_decode_1.default)(Buffer.from(sessionToken, "base64").toString());
return (0, lodash_1.get)(tokenPayload, "sessionId");
}