import { HttpModule, HttpService } from '@nestjs/axios'; import { Inject, Injectable, Module } from '@nestjs/common'; import axios, { AxiosInstance } from 'axios'; import { AsyncLocalStorageModule } from './AsyncLocalStorageModule'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { AsyncLocalStorage } from 'async_hooks'; import { AuthContext } from './interface'; import { CHeaderFields, EEnvConfig } from './constant.config'; export interface ResponseWrapper { code: string; data: T; message: string; totalElements: number; } export enum AXIOS_PROVIDER { INTERNAL = 'INTERNAL_INSTANCE_TOKEN', EXTERNAL = 'EXTERNAL_INSTANCE_TOKEN', } @Injectable() export class InternalHttpService extends HttpService { constructor( @Inject(AXIOS_PROVIDER.INTERNAL) override instance: AxiosInstance, private readonly configService: ConfigService, private readonly als: AsyncLocalStorage, ) { super(instance); instance.interceptors.response.use( (response) => { return response; }, (error) => { console.log({ url: error.config.url, method: error.config.method, headers: error.config.headers, params: error.config.params, }) return Promise.reject(error); }, ); instance.interceptors.request.use((config) => { if (config.params) { Object.keys(config.params).forEach((param) => { if (Array.isArray(config.params[param])) { config.params[param] = config.params[param].join(','); } }); } const internalUsername = this.configService.get(EEnvConfig.INTERNAL_USERNAME); const internalPassword = this.configService.get(EEnvConfig.INTERNAL_PASSWORD); const authContext = this.als.getStore(); config.headers[CHeaderFields.AUTHORIZATION] = `Basic ${Buffer.from(`${internalUsername}:${internalPassword}`).toString('base64')}`; if (!authContext) { return config; } config.headers[CHeaderFields.USER_ID] = authContext.userId; config.headers[CHeaderFields.WORKSPACE_ID] = authContext.workspaceId; config.headers[CHeaderFields.WORKSPACE_TYPE] = authContext.workspaceType; config.headers[CHeaderFields.AUTHORITIES] = config.headers[CHeaderFields.AUTHORITIES] ? config.headers[CHeaderFields.AUTHORITIES] : authContext.authorities; return config; }); } } @Injectable() export class ExternalHttpService extends HttpService { constructor(@Inject(AXIOS_PROVIDER.EXTERNAL) override instance: AxiosInstance) { super(instance); instance.interceptors.response.use( (response) => { return response; }, (error) => { console.log({ url: error.config.url, method: error.config.method, headers: error.config.headers, params: error.config.params, }) return Promise.reject(error); }, ); instance.interceptors.request.use((config) => { if (config.params) { Object.keys(config.params).forEach((param) => { if (Array.isArray(config.params[param])) { config.params[param] = config.params[param].join(','); } }); } return config; }); } } @Module({ imports: [HttpModule, ConfigModule, AsyncLocalStorageModule], providers: [ { provide: AXIOS_PROVIDER.INTERNAL, useFactory: () => axios.create(), }, { provide: AXIOS_PROVIDER.EXTERNAL, useFactory: () => axios.create(), }, InternalHttpService, ExternalHttpService, ], exports: [InternalHttpService, ExternalHttpService], }) export class HttpServiceModule { }