Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to log all Axios external http requests in NestJS

I want to be able to log each axios request with full url, headers, etc but currently didn't find a way to do so.

What I did achieve so far is to writhe an Http Interceptor based on this answer

export class HttpLoggerInterceptor implements NestInterceptor {
  intercept(
    context: ExecutionContext,
    call$: Observable<any>,
  ): Observable<any> {
    return call$.pipe(
      map(data => {
        // pipe call to add / modify header(s) after remote method
        const req = context.switchToHttp().getRequest();
        return data;
      }),
    );
  }
}

Now I browse through the objects req and context props on debug but could not see Asios request url, etc. Unless I missed that.

My controller route (api/data in that case) have N number of http external calls taking place but interceptor intercepts only controller controller call not Axios calls.

Any thoughts?

That is context object:

args:Array(2) [IncomingMessage, ServerResponse]
constructorRef:class AppController { … }
getRequest:() => …
getResponse:() => …
handler:data() { … }
__proto__:Object {constructor: , getClass: , getHandler: , …}

that is req:

_dumped:false
_events:Object {}
_eventsCount:0
_maxListeners:undefined
_parsedOriginalUrl:Url {protocol: null, slashes: null, auth: null, …}
_parsedUrl:Url {protocol: null, slashes: null, auth: null, …}
_readableState:ReadableState {objectMode: false, highWaterMark: 16384, buffer: BufferList, …}
baseUrl:""
body:Object {}
client:Socket {connecting: false, _hadError: false, _handle: TCP, …}
complete:true
connection:Socket {connecting: false, _hadError: false, _handle: TCP, …}
destroyed:false
fresh:false
headers:Object {accept: "application/json, text/plain, */*", user-agent: "axios/0.18.0", host: "localhost:3000", …}
host:"localhost"
hostname:"localhost"
httpVersion:"1.1"
httpVersionMajor:1
httpVersionMinor:1
ip:"::ffff:127.0.0.1"
ips:Array(0)
method:"GET"
next:function next(err) { … }
originalUrl:"/api/data"
params:Object {}
__proto__:Object {constructor: , __defineGetter__: , __defineSetter__: , …}
path:"/api/data"
protocol:"http"
query:Object {}
rawHeaders:Array(8) ["Accept", "application/json, text/plain, */*", "User-Agent", …]
rawTrailers:Array(0) []
readable:true
readableBuffer:BufferList
readableFlowing:null
readableHighWaterMark:16384
readableLength:0
res:ServerResponse {_events: Object, _eventsCount: 1, _maxListeners: undefined, …}
route:Route {path: "/api/data", stack: Array(1), methods: Object}
secure:false
socket:Socket {connecting: false, _hadError: false, _handle: TCP, …}
stale:true
statusCode:null
statusMessage:null
subdomains:Array(0)
trailers:Object {}
upgrade:false
url:"/api/data"
xhr:false
like image 999
sreginogemoh Avatar asked Jan 01 '23 10:01

sreginogemoh


1 Answers

Nest.js-Interceptors only process the request handled by your controller and the response going out. If you make http requests with Axios while you handle a controller request, they won't be processed by an interceptor.


Axios Interceptor

The HttpService exposes its axios instance directly via get axiosRef(). With it, you can add an axios interceptor:

this.httpService.axiosRef.interceptors.request.use(config => { /*...*/ return config })

You can for example do that in the onModuleInit() of your AppModule.


Delegate to Facade

As an alternative, you can create an HttpService facade, that logs the request and delegates all calls to the built-in HttpService:

@Injectable()
export class MyHttpService {
  private logger: Logger = new Logger(MyHttpService.name);

  constructor (private httpService: HttpService) {}
  
  public get<T = any>(url: string, config?: AxiosRequestConfig): Observable<AxiosResponse<T>> {
    this.logger.log({url, config});
    return this.httpService.get(url, config)
       .pipe(tap(response => this.logger.log(response)));
  }

  // ... all the other methods you need.

}

You can create your own LoggingHttpModule that imports the built-in HttpModule and exports your MyHttpService.

like image 90
Kim Kern Avatar answered Jan 04 '23 17:01

Kim Kern