UNPKG

@jiaxinjiang/nest-http

Version:

Http request component for NestJs.

180 lines (170 loc) 5.13 kB
import { AxiosRequestConfig, AxiosResponse } from 'axios'; import { Inject, Injectable, HttpService, LoggerService, Logger, } from '@nestjs/common'; import { HttpRequestApiException } from './http.exception'; import { HttpHepler } from './http.helper'; import { HTTP_OPTION } from './http.constants'; import { RequestConfig, ParameterStyle, ResponseSchema, } from './http.interface'; @Injectable() export class HttpFetchService { private logger: Logger | LoggerService; constructor( @Inject(HttpService) private httpService: HttpService, @Inject(HTTP_OPTION) private httpOption: RequestConfig, ) { const { logger, requestInterceptors = [], responseInterceptors = [] } = this.httpOption; this.logger = logger || new Logger(HttpFetchService.name); requestInterceptors.forEach( ({ onFulfilled, onRejected }) => { this.httpService.axiosRef.interceptors.request.use( onFulfilled, onRejected, ); }, ); this.httpService.axiosRef.interceptors.response.use( response => response, error => { const { response = {}, config = {} } = error; this.logger.error( `Api request failed -> status: ${response.status}; url: ${ config.url }; params: ${JSON.stringify( config.params || {}, )}; body: ${JSON.stringify( config.data || {}, )}; response: ${JSON.stringify(response.data)}`, ); throw error; }, ); responseInterceptors.forEach( ({ onFulfilled, onRejected }) => { this.httpService.axiosRef.interceptors.response.use( onFulfilled, onRejected, ); }, ); } private async request<T = any>(url: string, config: AxiosRequestConfig = {}) { config = config || {}; const protocol = this.httpOption.protocol || 'http'; if (url.indexOf(protocol) !== 0) { url = `${protocol}://${url}`; } switch (this.httpOption.parameterStyle) { case ParameterStyle.CAMEL_TO_SNAKE: if (config.data) { config.data = HttpHepler.humpToSnake<T>(config.data); } if (config.params) { config.params = HttpHepler.humpToSnake<T>(config.params); } break; case ParameterStyle.SNAKE_TO_CAMEL: if (config.data) { config.data = HttpHepler.snakeToHump<T>(config.data); } if (config.params) { config.params = HttpHepler.snakeToHump<T>(config.params); } break; default: break; } let response: ResponseSchema<T>, resp: AxiosResponse<T>; const stringParams = JSON.stringify(config.params || {}); const stringBody = JSON.stringify(config.data || {}); const start: number = new Date().getTime(); try { resp = await this.httpService.axiosRef.request<T>({ ...this.httpOption, ...config, url, }); url = resp.config.url; this.logger.log( `Api request -> (${new Date().getTime() - start}ms) url: ${url}; params: ${stringParams}; body: ${stringBody}`, ); const data = resp.data as any; let content = data.data; if (this.httpOption.parameterStyle === ParameterStyle.CAMEL_TO_SNAKE) { content = HttpHepler.snakeToHump<T>(data.data || {}); } else if ( this.httpOption.parameterStyle === ParameterStyle.SNAKE_TO_CAMEL ) { content = HttpHepler.humpToSnake<T>(data.data || {}); } response = { code: data.code || 0, msg: data.msg || '', data: content, success: data.code === 600, } as ResponseSchema<T>; } catch (err) { this.logger.error(err.message); if (!err.response.data) { err.response.data = {} } if (!err.response.data.code && !err.response.data.data) { throw new HttpRequestApiException({ msg: err.message, }); } response = { code: err.response.data.code || 0, msg: err.response.data.msg || err.message, data: err.response.data.data, success: false, } as ResponseSchema<T>; } return response; } async post<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'post', }); } async get<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'get', }); } async put<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'put', }); } async delete<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'delete', }); } async patch<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'patch', }); } async head<T = any>(url: string, config?: AxiosRequestConfig) { return this.request<T>(url, { ...config, method: 'head', }); } }