Search code examples
typescriptnestjsinterceptor

How to catch exception in interceptor inside catchError operator


I'm making a logging interceptor to log every http calls of an API,In happy path everything works fine but when I throw an exception I'm getting in Postman a 200 status from thrown exception (with status 400) from the controller and passed through the interceptor. I've read this and use it in interceptor class but I tried some way and I'm getting differents errors, How can I get an approach that I could use to throw the status that I need and also passing through the interceptor?. here is my interceptor and the exception class i'm trying to use from documentation:

    @Injectable()
    export class LogsInterceptor<T> implements NestInterceptor<T> {
      constructor(
        private logService: LogsService,
        private jwtService: JwtService,
      ) {}
    
      intercept(
        context: ExecutionContext,
        next: CallHandler<any>,
      ): Observable<any> {
        const request = context.switchToHttp().getRequest();
        let responseStatus = context.switchToHttp().getResponse();
        let log: ILogModel;
        let id: number;
        let args: any = context.getArgs()[0];
    
        console.log('before');
        return next.handle().pipe(
          map(async (data) => {
            id = this.setId(args, id, data);
            log = {
              ip: args.hostname,
              id,
              tipo: args.method,
              path: args.originalUrl,
              query: args.query,
              params: args.params,
              body: args.body,
              token: args.headers.authorization,
              response: data,
              statuscode: responseStatus.statusCode,
            };
            let idT: number = 0;
            idT = await this.logRequest(log);
            console.log(args.route.path);
            let respuestaF = {};
            if (
              args.route.path == '/cards/:pan' ||
              args.route.path == '/cards/:pan/paymentRequest'
            ) {
              delete data[0].code;
              delete data[0].solicitud;
              respuestaF = {
                requestId: idT,
                message: data[0].message,
                companyid: data[0].companyid,
                expirationdate: data[0].expirationdate,
                licenseplate: data[0].licenseplate,
              };
            } else {
              respuestaF = {
                requestId: idT,
                data,
              };
            }
            console.log('after');
            return respuestaF;
          }),
          catchError(async (error: any) => {
            console.log(request.statusCode);
            console.log(responseStatus.statusCode);
            id = this.setId(args, id, error);
            log = {
              ip: args.hostname,
              id,
              tipo: args.method,
              path: args.originalUrl,
              query: args.query,
              params: args.params,
              body: args.body,
              token: args.headers.authorization,
              response: error,
              statuscode: error.status,
            };
            let idT: number = 0;
            idT = await this.logRequest(log);
            let respuestaF = {
              requestId: idT,
              error,
            };
    // if (error instanceof HttpException) {
    //   console.log('httpexcpcion');
    //   return throwError(
    //     () => new HttpException(respuestaF, HttpStatus.BAD_REQUEST),
    //   );
    // }
            console.log(log);
            console.log(responseStatus.statusCode);
            console.log('entrado por error');
            return respuestaF;
          }),
        );
      }
}

Here's how it looks the response, status 200 and in the body the messages of my thrown exception:

enter image description here


Solution

  • You can achieve an approach, you'll need to make a new exception package to customize the message of the exception but at least you are sending a 400 status code in the response, it's two lines but it will get you close to what you want, at the end of the catchError operator you ask if it's a HttpException instance and throw a Build-in exception from @nestjs/common, if you add a status to the thrown exception return a 200 status code, or if you change anything of the exception return 200 status code:

    if(error instanceof HttpException){
    throw new BadRequestException(respuestaF);
    }
    

    this way you are sending a generic 400 and inside all the info you can get of the exception, it's not a standar response but at least the client will know that something went wrong with his request