import * as request from 'request-promise'; const BASE_JSON_OPTIONS = { json: true, }; export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; export interface IRequestOptions { body?: {}; qs?: {}; headers?: { [key: string]: string, }; } export interface IRequestContext { request: { headers?: { [key: string]: string, }; }; } export class RequestWrapper { private static buildUrl = (baseUrl: string, path: string) => { return `${baseUrl}${path}`; } private static interceptRequestError = error => { // Append request url to error message error.message = `${error.message} - ${error.options.url}`; throw error; } private static getMergedOptions = (options?: IRequestOptions, context?: IRequestContext): IRequestOptions => { if (!context || !options) { return options; } // Merge required options with tracing from request context return Object.assign({}, options, { headers: Object.assign({}, options.headers ? options.headers : {}, { 'x-request-id': context.request.headers['x-request-id'], 'x-b3-traceid': context.request.headers['x-b3-traceid'], 'x-b3-spanid': context.request.headers['x-b3-spanid'], 'x-b3-parentspanid': context.request.headers['x-b3-parentspanid'], 'x-b3-sampled': context.request.headers['x-b3-sampled'], 'x-b3-flags': context.request.headers['x-b3-flags'], 'x-ot-span-context': context.request.headers['x-ot-span-context'], }), }); } private baseUrl: string; constructor(baseUrl: string) { this.baseUrl = baseUrl; } public buildJsonRequest = ( path: string, method: Method = 'GET', options?: IRequestOptions, context?: IRequestContext) => { return Object.assign({}, BASE_JSON_OPTIONS, { url: RequestWrapper.buildUrl(this.baseUrl, path), method, }, RequestWrapper.getMergedOptions(options, context)); } /** * Proxy standard JSON request * @param path relative URL path * @param method HTTP method * @param options request options * @deprecated Since 1.2.0. Use proxyCorrelatedJsonRequest instead. */ public async proxyJsonRequest(path: string, method: Method = 'GET', options?: IRequestOptions): Promise { return request(this.buildJsonRequest(path, method, options)).catch(RequestWrapper.interceptRequestError); } /** * Proxy standard JSON request * @param path relative URL path * @param method HTTP method * @param context request context * @param options request options */ public async proxyCorrelatedJsonRequest( path: string, method: Method = 'GET', context: IRequestContext, options?: IRequestOptions, ): Promise { return request(this.buildJsonRequest(path, method, options, context)).catch(RequestWrapper.interceptRequestError); } } export function createWrapper(baseUrl: string) { return new RequestWrapper(baseUrl); }