Specific use of exception filter Exceptionfilter in nestjs

Specific use of exception filter Exceptionfilter in nestjs

Speaking of Nestjs exception filter, we have to mention .Net's global filter, which is quite powerful. In theory, it is called AOP aspect-oriented programming, which facilitates too many scenarios that require exception handling. Back to the exception filter of Nestjs, it implements similar functions and adopts similar processing methods, but one is for C# and the other is for Nodejs. Fortunately, I have found similar things in both frameworks.

Aspect-Oriented Programming (AOP) is something similar to a programming specification. Its fellow practitioners also call it interface-oriented programming, SOLID principles, and so on.

Exception handling in Nestjs

Default exception handling

Nestjs has a built-in default global exception filter that handles exceptions that can be converted into HttpException.

If it is an HttpException or its subclass exception, the JSON format of the exception will be returned:

{"exceptionCode":40005,"message":"Custom exception","path":"/"}

If it is not an HttpException or its subclass exception, it will return:

{"statusCode":500,"message":"Internal server error"}

Since Nestjs uses built-in default exception handling, there will be no program crash due to uncaught exceptions.

Custom exception filter handling

Since the return value format of built-in exception handling cannot be adjusted, custom exceptions are normal. Custom exceptions can customize the returned exception information and add custom exception codes to facilitate client personnel to display differently according to the exception codes.

How to customize exceptions?

Not reinventing the wheel is a programmer's self-restraint. First, we create our own exception base class:

import { HttpException } from "@nestjs/common";

/**
 * Define the base exception class *
 * @export
 * @class BaseException
 * @extends {HttpException}
 */
export class BaseException extends HttpException {

  /**
   * Creates an instance of BaseException.
   * @param {number} exceptionCode custom exception number* @param {string} errorMessage prompt message* @param {number} statusCode status code* @memberof BaseException
   */
  constructor(public exceptionCode: number, public errorMessage: string, public statusCode: number) {
    super({ exceptionCode: exceptionCode, errorMessage: errorMessage }, statusCode);
  }

  /**
   * Get custom exception code *
   * @return {*}
   * @memberof BaseException
   */
  getExceptionCode(): number {
    return this.exceptionCode;
  }

  getErrorMessage(): string {
    return this.errorMessage;
  }

  getStatusCode(): number {
    return this.statusCode;
  }
}

Then we create a new unauthorized exception type, which adds a custom exception code:

import { HttpStatus } from "@nestjs/common";
import { BaseException } from "./base.exception";

export class UnCauhtException extends BaseException {
  constructor() {
    super(40000, "System operation abnormality, please contact the administrator!", HttpStatus.FORBIDDEN);
  }
}

Now that we have created a custom exception, we need to handle unauthorized exceptions. First, create a new custom exception handling base class. Please note that we use Express here:

import { ArgumentsHost, ExceptionFilter, HttpException } from "@nestjs/common";
import { HttpArgumentsHost } from "@nestjs/common/interfaces";
import { BaseException } from "src/exceptions/base.exception";
import { Response, Request } from "express";

/**
 * Abnormal base class filter *
 * @export
 * @class BaseExceptionFilter
 * @implements {ExceptionFilter<BaseException>}
 */
export abstract class BaseExceptionFilter implements ExceptionFilter<BaseException>
{
  /**
   *Exception class capture*
   * @abstract
   * @param {BaseException} exception
   * @param {ArgumentsHost} host
   * @memberof BaseExceptionFilter
   */
  abstract catch(exception: BaseException, host: ArgumentsHost);

  /**
   * Get http request context parameters *
   * @protected
   * @param {ArgumentsHost} host
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getHttpContext(host: ArgumentsHost) {
    return host.switchToHttp();
  }

  /**
   * Get http response parameters *
   * @protected
   * @param {HttpArgumentsHost} httpContext
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getResponse(httpContext: HttpArgumentsHost): Response {
    return httpContext.getResponse<Response>();
  }

  /**
   * Get http request parameters *
   * @protected
   * @param {HttpArgumentsHost} httpContext
   * @return {*}
   * @memberof BaseExceptionFilter
   */
  protected getRequest(httpContext: HttpArgumentsHost): Request {
    return httpContext.getRequest<Request>();
  }

  /**
   * Write exception information to the client *
   * @param {ArgumentsHost} host
   * @param {BaseException} exception
   * @memberof BaseExceptionFilter
   */
  protected writeToClient(host: ArgumentsHost, exception: BaseException) {
    const ctx = this.getHttpContext(host);
    if (exception instanceof BaseException) {
      this.getResponse(ctx).status(exception.statusCode).json({
        exceptionCode: exception.getExceptionCode(),
        message: exception.getErrorMessage(),
        path: this.getRequest(ctx).url
      });
    }else {
      const httpException=exception;
      this.getResponse(ctx).status(500).json({
        message: "Unhandled exception",
        path: this.getRequest(ctx).url
      });
    }

  }
}

Create a new unauthorized exception handler:

import { ArgumentsHost, Catch } from "@nestjs/common";
import { AuthException } from "src/exceptions/auth.exception";
import { BaseException } from "src/exceptions/base.exception";
import { BaseExceptionFilter } from "./base.exception.filter";

@Catch(AuthException)
export class AuthExceptionFilter extends BaseExceptionFilter
{
  constructor(){
    super();
    console.log("Authorization exception constructor initialization"+new Date().toISOString());
  }
  catch(exception: AuthException, host: ArgumentsHost) {
    exception.exceptionCode=40002;
    console.log("Authorization exception execution"+new Date().toISOString());
    this.writeToClient(host,exception);
  }

}

Here are some explanations for the unauthorized exception handling class:

  1. Added Catch annotation to catch only Authexception exceptions, and other types of exceptions are not processed
  2. Inherit the custom exception handling class Baseexceptionfilter

Application

Exception handling classes can be applied to methods, controllers, or globally. Even the same Controller can define multiple custom exception classes.

import { Controller, ForbiddenException, Get, HttpException, HttpStatus, UseFilters } from '@nestjs/common';
import { AppService } from './app.service';
import { AuthException } from './exceptions/auth.exception';
import { BusinessException } from './exceptions/business.exception';
import { UnCauhtException } from './exceptions/uncauht.exception';
import { AuthExceptionFilter } from './filters/auth.exception.filter';
import { BusinessExceptionFilter } from './filters/business.exception.filter';


/**
 * Basic controller example with a single route
 */
@UseFilters(AuthExceptionFilter,BusinessExceptionFilter)
@Controller()
export class AppController {
 constructor(private readonly appService: AppService) {}

 @Get()
 getHello(): string {
  //throw new Error("666");
  throw new BusinessException("custom exception",HttpStatus.OK);
  throw new AuthException();
  throw new HttpException("custom exception",HttpStatus.FORBIDDEN);
  return this.appService.getHello();
 }

 @Get("name")
 getName():string
 {
  return "guozhiqi";
 }
}

A few notes:

  1. We use the Usefilters annotation to add exception filters
  2. We define two different types of custom exception handling classes in Appcontroller
  3. That is, the exceptions thrown in our Appcontroller can be handled normally as long as they are the two types we defined.

A few questions

How many times will our custom exception handling class in Usefitlers be initialized?
Answer: The custom exception class that we register to AppController by type will only be initialized once when the program is initialized. That is to say, after the program starts, each

The exception handling classes defined by the controller and each method have been determined.
What happens if we catch the exception but don't do anything with it?
Answer: If our exception handling method does nothing, then congratulations, you will successfully hang the browser request, because the exception is not handled, so the browser will not get a response.

What is the order in which multiple exceptions are handled?
Answer: If multiple exception handlers can catch the exception, only the first one is valid. That is to say, the exception handling class is different from the middleware. Only one of the exception handling classes can handle it, while the middleware needs to handle both.

Who is Nestjs's @Usefilters like?
First of all, from the JS perspective, it is like Angular. If you look at the backend, it is most like Spring.

Nestjs's exception handling is not complicated. What is complicated is that we need to handle different types of exceptions and extract the commonalities of the exceptions.

Reference document: docs.nestjs.cn

This is the end of this article about the specific use of the exception filter Exceptionfilter in nestjs. For more related nest exception filter Exceptionfilter content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How to use ExceptionFilter in .Net Core
  • asp.net core MVC global filter ExceptionFilter filter (1)

<<:  Detailed introduction to nobody user and nologin in Unix/Linux system

>>:  Simple implementation of ignoring foreign key constraints when deleting MySQL tables

Recommend

An article to give you a deep understanding of Mysql triggers

Table of contents 1. When inserting or modifying ...

Four ways to modify the default CSS style of element-ui components in Vue

Table of contents Preface 1. Use global unified o...

Alibaba Cloud domain name and IP binding steps and methods

1 Enter the Alibaba Cloud console, find the domai...

When to use table and when to use CSS (experience sharing)

The main text page of TW used to have a width of 8...

How to use limit_req_zone in Nginx to limit the access to the same IP

Nginx can use the limit_req_zone directive of the...

JavaScript file loading and blocking issues: performance optimization case study

Let me start with a question: When writing an HTM...

Clever use of webkit-box-reflect to achieve various dynamic effects (summary)

In an article a long time ago, I talked about the...

Mysql master-slave synchronization Last_IO_Errno:1236 error solution

What is the reason for the Last_IO_Errno:1236 err...

Java programming to write a JavaScript super practical table plug-in

Table of contents Effects Documentation first ste...

JavaScript implements displaying a drop-down box when the mouse passes over it

This article shares the specific code of JavaScri...

Shell script to monitor MySQL master-slave status

Share a Shell script under Linux to monitor the m...

【HTML element】How to embed images

The img element allows us to embed images in HTML...

Linux parted disk partition implementation steps analysis

Compared with fdisk, parted is less used and is m...