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

How to quickly modify the host attribute of a MySQL user

When you log in to MySQL remotely, the account yo...

In-depth interpretation of /etc/fstab file in Linux system

Preface [root@localhost ~]# cat /etc/fstab # # /e...

Tutorial on installing mysql5.7.23 on Ubuntu 18.04

This article shares with you the specific method ...

Differences and comparisons of storage engines in MySQL

MyISAM storage engine MyISAM is based on the ISAM...

Use of docker system command set

Table of contents docker system df docker system ...

About ROS2 installation and docker environment usage

Table of contents Why use Docker? Docker installa...

A possible bug when MySQL executes the sum function on the window function

When using MySql's window function to collect...

How to implement Nginx configuration detection service status

1. Check whether the check status module is insta...

XHTML Getting Started Tutorial: XHTML Tags

Introduction to XHTML tags <br />Perhaps you...

MySQL permissions and database design case study

Permissions and database design User Management U...

How to modify the initial password of MySQL on MAC

Problem description: I bought a Mac and installed...

Common operation commands of MySQL in Linux system

Serve: # chkconfig --list List all system service...

How to mount a disk in Linux and set it to automatically mount on boot

Knowing that everyone's time is precious, I w...

30 Tips for Writing HTML Code

1. Always close HTML tags In the source code of p...

Build Maven projects faster in Docker

Table of contents I. Overview 2. Conventional mul...