Exception Filters là gì? Xử lý Unhandled Error trong NestJS

Exception Filters

Trong quá trình coding thì chúng ta sẽ không thể tránh khỏi những trường hợp lỗi không mong muốn và nếu như chúng ta throw ra lỗi đó qua phía client thì có thể dẫn đến lỗi bảo mật hay trải nghiệm người dùng không tốt.

Để khắc phục tình trạng này thì NestJS có một Exception Layer. Layer này sẽ catch tất cả unhandled error và xử lý nó trước khi trả về Controller. Và tất nhiên chúng ta cũng có thể custom response hay handle lại error này trước khi nó được trả về.

Default Response

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

Xử lý Error với Exception Filters

Để có thể handle sao cho phù hợp với từng loại Error thì chúng ta có thể Catch những Error mà ta mong muốn

JavaScript
@Catch(HttpException) // Http Error

@Catch(PrismaException) // Database Error

@Catch(CustomErrorInstance) // Custom Error

Sau khi đã Catch được Error mà mình mong muốn thì chúng ta sẽ phải implement lại class ExceptionFilter của NestJS và handle Error.

JavaScript
@Catch()
export class InternalExceptionFilter implements ExceptionFilter {
  async catch(exception: HttpException, context: GqlExecutionContext) {
    if (exception instanceof HttpException) {
      if (exception.getStatus() !== 500) return exception;
    }
    //Handle Error on production environment
    if (process.env.NODE_ENV !== "development") {
      const ctx = GqlExecutionContext.create(context).getContext();
      const req: Request & { user: Partial<User> | null } = ctx.req;
      const { query, operationName, variables } = req.body;
      const authorization = {
        laboId: req.header("labo-id"),
        userId: req.user?.databaseId,
      };

      const errorParams: ErrorTemplateParams = {
        hostname: req.hostname,
        query,
        payload: JSON.stringify({ operationName, variables }, null, 2),
        stack: exception.stack,
        errorName: exception.name,
        authorization: JSON.stringify(authorization, null, 2),
      };

      const slack = new SlackService();
      slack.sendMessage(errorParams);
      // Return default error response
      return new InternalServerErrorException("Internal_Error");
    }
    // return error + stacktrace
    return exception;
  }
}

Thì ở đây mình đã Catch tất cả Error bao gồm Http ErrorDatabase Error chỉ ngoại trừ những lỗi 4xx đã throw ra.

Ở đây chúng ta có 2 tham số đó làm exceptioncontext thì nó là cái gì?

exception ở đây nó là lỗi nguyên bản nó thuộc về instance của Error. Thì trong exception nó sẽ bao gồm: stacktrace, message, errorName và error.

context này nó được coi là host, chúng ta có thể sử dụng context này để có thể tham chiếu đến RequestResponse và có thể custom lại Error chi tiết hơn để có thể tracking bug dễ dàng hơn.

Custom Response

Và cuối cùng để NestJS có thể nhận được Exception Filter này thì t cần phải binding nó vào để có thể sử dụng như một global Filter.

main.ts
// Handle Internal Error
  if (process.env.NODE_ENV !== "development") {
    app.useGlobalFilters(new InternalExceptionFilter());
  }

Kết bài:

NestJS là framework hỗ trợ mạnh mẽ với nhiều tính năng và Exception Filters là một trong số đó. Thì ở bài này chúng ta đã tìm hiểu qua ExceptionFilter là gì và Handle những Unhandled Error như thế nào.

Hẹn gặp lại mọi người trong bài viết tìm hiểu về NestJS khác.

0 Shares:
1 comment
  1. Cho tớ hỏi xíu với bạn ơi
    Những catch dưới đây mình sẽ đặt ở những controller mà mình muốn catch exception khi đã set global InternalExceptionFilter phải không nhỉ.
    @Catch(HttpException) // Http Error
    @Catch(PrismaException) // Database Error
    @Catch(CustomErrorInstance) // Custom Error

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like
Read More

MOVE ON

Trong cuộc sống thường ngày đang có rất nhiều người bị mắc kẹt trong những nỗi đau từ…