UNPKG

@elastic.io/maester-client

Version:
147 lines (146 loc) 6.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StorageClient = exports.getStreamWithContentType = void 0; /* eslint-disable no-continue,default-param-last */ const axios_1 = __importDefault(require("axios")); const util_1 = require("util"); const http_1 = __importDefault(require("http")); const https_1 = __importDefault(require("https")); const jsonwebtoken_1 = require("jsonwebtoken"); const stream_mime_type_1 = require("stream-mime-type"); const logger_1 = __importDefault(require("./logger")); const package_json_1 = __importDefault(require("../package.json")); const errors_1 = require("./errors"); const utils_1 = require("./utils"); const interfaces_1 = require("./interfaces"); const getStreamWithContentType = async (getStream) => { const { mime = 'application/json', stream } = await (0, stream_mime_type_1.getMimeType)(await getStream(), { strict: true }); return { mime, stream }; }; exports.getStreamWithContentType = getStreamWithContentType; class StorageClient { constructor(config) { this.api = axios_1.default.create({ baseURL: config.uri, httpAgent: StorageClient.httpAgent, httpsAgent: StorageClient.httpsAgent, maxContentLength: Infinity, maxRedirects: 0 }); this.userAgent = `${config.userAgent || ''} axios/${package_json_1.default.dependencies.axios}`; this.msgId = config.msgId || ''; this.jwtSecret = config.jwtSecret; } async requestRetry(requestConfig, retryOptions) { var _a; const { retriesCount, requestTimeout } = (0, utils_1.validateAndGetRetryOptions)(retryOptions); let currentRetries = 0; let res; let err; while (currentRetries <= retriesCount) { err = null; res = null; try { const { axiosReqConfig, getFreshStream } = requestConfig; let bodyAsStream; if (getFreshStream) { const { mime, stream } = await (0, exports.getStreamWithContentType)(getFreshStream); if (!axiosReqConfig.headers[interfaces_1.CONTENT_TYPE_HEADER]) axiosReqConfig.headers[interfaces_1.CONTENT_TYPE_HEADER] = mime; bodyAsStream = stream; } res = await this.api.request({ ...axiosReqConfig, data: bodyAsStream, timeout: requestTimeout }); } catch (e) { if (e instanceof errors_1.ObjectStorageClientError) { throw e; } err = e; if (((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.status) < 500) throw new errors_1.ClientTransportError(`Client error during request: ${err.message}`, err.response.status); } if ((err || res.status >= 500) && currentRetries < retriesCount) { logger_1.default.warn({ err, status: res === null || res === void 0 ? void 0 : res.status, statusText: res === null || res === void 0 ? void 0 : res.statusText }, `Error during object request, retrying (${currentRetries + 1})`); await (0, utils_1.exponentialSleep)(currentRetries); currentRetries++; continue; } break; } if (err || (res === null || res === void 0 ? void 0 : res.status) >= 500) { throw new errors_1.ServerTransportError(`Server error during request: "${(err === null || err === void 0 ? void 0 : err.message) || 'unknown error'}"`, { code: res === null || res === void 0 ? void 0 : res.status, cause: err }); } return res; } async formHeaders(jwtPayloadOrToken, headers) { if (typeof jwtPayloadOrToken !== 'string' && !this.jwtSecret) { throw new errors_1.JwtNotProvidedError('Neither JWT token passed, nor JWT secret provided during initialization'); } const token = typeof jwtPayloadOrToken === 'string' ? jwtPayloadOrToken : await (0, util_1.promisify)(jsonwebtoken_1.sign)(jwtPayloadOrToken, this.jwtSecret); return { Authorization: `Bearer ${token}`, 'User-Agent': this.userAgent, 'x-request-id': `f:${process.env.ELASTICIO_FLOW_ID};s:${process.env.ELASTICIO_STEP_ID};m:${this.msgId}`, ...headers }; } // wrap for 'post' and 'put' methods async reqWithBody(getFreshStream, { headers = {}, jwtPayloadOrToken = this.jwtSecret, retryOptions = {} } = {}, objectId) { return this.requestRetry({ getFreshStream, axiosReqConfig: { method: objectId ? 'put' : 'post', url: objectId ? `/objects/${objectId}` : '/objects', headers: await this.formHeaders(jwtPayloadOrToken, headers) }, }, retryOptions); } async post(getFreshStream, reqWithBodyOptions) { return this.reqWithBody(getFreshStream, reqWithBodyOptions); } async put(objectId, getFreshStream, reqWithBodyOptions) { return this.reqWithBody(getFreshStream, reqWithBodyOptions, objectId); } /** * fetches object(s) from maester by id/params * @param searchCriteria objectId/request-params */ async get(searchCriteria, { jwtPayloadOrToken = this.jwtSecret, retryOptions = {} }) { const byId = typeof searchCriteria === 'string'; return this.requestRetry({ axiosReqConfig: { method: 'get', url: byId ? `/objects/${searchCriteria}` : '/objects', responseType: 'stream', params: byId ? {} : searchCriteria, headers: await this.formHeaders(jwtPayloadOrToken) } }, retryOptions); } /** * delete object(s) from maester by id/params * @param searchCriteria objectId/request-params */ async delete(searchCriteria, { jwtPayloadOrToken = this.jwtSecret, retryOptions = {} }) { const byId = typeof searchCriteria === 'string'; return this.requestRetry({ axiosReqConfig: { method: 'delete', url: byId ? `/objects/${searchCriteria}` : '/objects', params: byId ? {} : searchCriteria, headers: await this.formHeaders(jwtPayloadOrToken) } }, retryOptions); } } exports.StorageClient = StorageClient; StorageClient.httpAgent = new http_1.default.Agent({ keepAlive: true }); StorageClient.httpsAgent = new https_1.default.Agent({ keepAlive: true });