preface

As the official says:

The built-inAbnormal layerResponsible for handling all exceptions thrown throughout the application.

When an unhandled exception is caught, the end user receives a friendly response.



NestJS provides a wave of ready-to-use built-in exception filters;

in@nestjs/commonInside, search “Exception” for “~”

Let’s take a concrete example (global exception filtering),

Based on the built-in exception filter implementation, using the third party log (PINO) to record the exception log,

Do some processing and the package returns information;

rendering

In actual combat

Generate a filter template based on the CLI
nest g f common/filters/http-exception
Copy the code

http-exception.filter.ts

// Date formatting library, very small, like moment style API
import * as dayjs from 'dayjs';

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
// Nest is based on express by default, so it can be imported directly
import { Request, Response } from 'express';
// Third-party loggers
import { Logger } from 'nestjs-pino';

// Catch the request exception type
// Multiple arguments can be passed, so you can set filters for multiple types of exceptions by separating them with commas.
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  // To plug the exception into the custom Logger, we must introduce the corresponding instance
  // Under the constructor declaration definition, passed in from outside
  constructor(private readonly logger: Logger) {}
  
  catch(exception: HttpException, host: ArgumentsHost) {
    // Convert request-related parameters into standard HTTP context
    // GPRC and WEBSOCKET can be converted directly
    // You can also get the context type of some parameters directly
    const ctx = host.switchToHttp();
    / / response body
    const response = ctx.getResponse<Response>();
    / / request body
    const request = ctx.getRequest<Request>();
    
    // Determine whether the status is a request exception, otherwise throw back an internal service error
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    
    // The time of the moment
    const nowDate = dayjs(Date.now()).format('YYYY-MM-DDTHH:mm:ss');
    
    // Package exception information
    const errorResponse = {
      statusCode: status,
      message: exception.message,
      error: exception.name,
      date: nowDate,
      path: request.url,
    };

    // Record abnormal information to the third-party Logger
    this.logger.error(
      ` 【${nowDate}${request.method} ${request.url} query:The ${JSON.stringify(
        request.query,
      )} params:The ${JSON.stringify(request.params)} body:The ${JSON.stringify(
        request.body,
      )}`.JSON.stringify(errorResponse),
      'HttpExceptionFilter',);// Plug back the response body, which is what the client request is aware ofresponse.status(status).json(errorResponse); }}Copy the code

The main entrance (main. Ts)

import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
import { Logger } from 'nestjs-pino';
import { NestFactory } from '@nestjs/core';
async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    cors: false.logger: false});// Get the Pino Logger instance
  const logger = app.get(Logger);
  // Nestjs-Pino replaces nest Logger
  app.useLogger(logger);


  // Set the global exception filter
  app.useGlobalFilters(new HttpExceptionFilter(logger));
  await app.listen(configService.get('SERVE_LISTENER_PORT'));
}
bootstrap()
Copy the code

app.module.ts

Providers can be used if a specific module is available, exporting them from the core module.

import { Module } from '@nestjs/common';
// All interceptors can use this mode.
import { APP_FILTER } from '@nestjs/core';
import { HttpExceptionFilter } from './common/filters/http-exception.filter';
@Module({
  providers: [{provide: APP_FILTER,
      useClass: HttpExceptionFilter,
    },
  ],
})
export class AppModule {}
Copy the code

The @global decorator can also achieve the effect of a Global module! This is not recommended for app.module, but for reuse modules that you need to export! This is just a demonstration

import { Module,Global } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';

@Global(a)@Module({
  providers: [{provide: APP_FILTER,
      useClass: HttpExceptionFilter,
    },
  ],
})
export class AppModule {}
Copy the code

@global () is recommended for external reuse and needs to become a Global module, such as

import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Global(a)@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService],
})
export class CatsModule {}
Copy the code

conclusion

Have wrong place please leave a message, will correct in time! Thanks for reading ~