UNPKG

@elastic.io/component-commons-library

Version:
100 lines (86 loc) 3.41 kB
import http from 'http'; import https from 'https'; import axios, { AxiosInstance } from 'axios'; import removeTrailingSlash from 'remove-trailing-slash'; import removeLeadingSlash from 'remove-leading-slash'; import { axiosReqWithRetryOnServerError, getErrMsg, getFacelessRetriesCount } from '../externalApi'; import { PlatformApiLogicClient } from '../platformApi/PlatformApiLogicClient'; export class FacelessRestClient { emitter; cfg; request; private readonly axiosInst: AxiosInstance; private accessToken: null; logger: any; platformClient: PlatformApiLogicClient; constructor(emitter, cfg, userAgent?: string, msgId?: string) { this.emitter = emitter; this.cfg = cfg; this.axiosInst = axios.create({ httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), }); this.cfg.resourceServerUrl = cfg.resourceServerUrl; this.accessToken = null; this.logger = emitter.logger; this.platformClient = new PlatformApiLogicClient(emitter, cfg, userAgent, msgId); } protected async addAuthenticationToRequestOptions(requestOptions) { if (!this.accessToken) { const { secretId } = this.cfg; if (secretId) { this.logger.debug('Fetching credentials by secretId'); const secret = await this.platformClient.fetchSecretById({ secretId }); this.accessToken = secret.attributes.credentials.access_token; } else { this.logger.debug('Fetching credentials from this.cfg'); this.accessToken = this.cfg.oauth.access_token; } } // eslint-disable-next-line no-param-reassign requestOptions.headers.Authorization = `Bearer ${this.accessToken}`; } // options expects the following sub-variables: // url: Url to call // method: HTTP verb to use // data: Body of the request, if applicable. Defaults to undefined. // headers: Any HTTP headers to add to the request. Defaults to {} // urlIsSegment: Whether to append to the base server url or // if the provided URL is an absolute path. Defaults to true async makeRequest(options) { const { url, method, data, headers = {}, urlIsSegment = true, } = options; const urlToCall = urlIsSegment ? `${removeTrailingSlash(this.cfg.resourceServerUrl.trim())}/${removeLeadingSlash(url.trim())}` // Trim trailing or leading '/' : url.trim(); this.logger.debug(`Making ${method} request...`); const requestOptions = { method, url: urlToCall, data, headers, }; let error; let currentRetry = 0; const facelessRetriesCount = getFacelessRetriesCount(); while (currentRetry < facelessRetriesCount) { await this.addAuthenticationToRequestOptions(requestOptions); try { const response = await axiosReqWithRetryOnServerError.call(this, requestOptions, this.axiosInst); return response; } catch (err) { this.logger.error(getErrMsg(err.response)); error = err; if (err.response?.status < 500 && err.response?.status !== 401) { throw err; } this.logger.info(`Request failed, faceless retrying(${1 + currentRetry})`); this.accessToken = null; currentRetry++; } } this.logger.error('The number of attempts to receive the proper token has been exhausted.'); throw error; } }