最近の公式文書Exception Filter


Exception Filters


Exception Filterは、nest全体で例外を簡単に処理できます.コードに例外が単独で処理されていない場合は、例外フィルタに移動して応答を送信します.
Http exceptionサブクラスを処理するために組み込まれたグローバル例外フィルタ.
{
"statusCode": 500,
"message": "Internal server error"
}
このシェイプのフィルタを返します.
Global Exception Filterセクションではhttp-errorsライブラリがサポートされています.status codeがあり、メッセージがある場合は返します.

Throw Standard Exception

@Get()
async findAll() {
  throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
同じように異常が発生する.HttpStatusは@nestjs/commonパッケージにあります.
@Get()
async findAll() {
  throw new HttpException({
    status: HttpStatus.FORBIDDEN,
    error: 'This is a custom message',
  }, HttpStatus.FORBIDDEN);
}
{
  "status": 403,
  "error": "This is a custom message"
}
オブジェクトは同じ方法で渡すことができますが、オブジェクトを渡すと応答が完全に変更され、文字列のみが入力されるとメッセージ部分のみが変更されます.

Custom Exceptions


直接Exceptionを作成し、HttpExceptionを継承して作成することができます.
export class ForbiddenException extends HttpException {
  constructor() {
    super('Forbidden', HttpStatus.FORBIDDEN);
  }
}
@Get()
async findAll() {
  throw new ForbiddenException();
}
同じ方法で使用します.

Built-in HTTP Exception


BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
HttpVersionNotSupportedException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableEntityException
InternalServerErrorException
NotImplementedException
ImATeapotException
MethodNotAllowedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException
PreconditionFailedException

Exception Filters


build-in exception filterは、多くのことを自動的に処理できますが、状況に応じて異なる処理はできません.たとえば、いくつかの例外が発生したときにログを残します.この場合exception filterを使用できます
Custom logicによりArgumentsHostを受け入れ,req,resを抽出することにより適用できる.
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}
すべてのHttpExceptionが発生した場合、この方法で処理できます.
すべての例外フィルタは、ExceptionFilterを実装する必要があります.
@Catch Decoratorでは、特定のExceptionのみをキャプチャできますが、分割を使用して複数のExceptionをキャプチャできます.

Arguments Host


catch()メソッドでは、パラメータから例外とhostを受信できます.例外は現在処理中のExceptionオブジェクトを表し、hostパラメータはArgumentHostを取得し、ArgumentHostはユーティリティオブジェクトです.
Req、Resなどが得られる.ArgumentHost
Argument HostはWebsocketもMicroserviceも使用できるため抽象化が多い.

Binding Filters

@Post()
@UseFilters(new HttpExceptionFilter())
//@UseFilters(HttpExceptionFilter)
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}
UserFiltersを使用してFilterを適用できます.もちろん、複数を同時に適用できるように区分されています.オブジェクトを追加することもできますが、classを追加することでDIと責任をフレームワークに少し移すこともできます.
可能であれば、classとしてinstanceより入れたほうがいいですが、メモリ使用量に差が出ます.Instanceは、すべてのモジュールで簡単に共有できます.
ユーザーフィルタはmethod scope、controller scope、global scopeに適用できます.
//클래스
@UseFilters(new HttpExceptionFilter())
export class CatsController {}

//전역
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();
しかし,ユーザグローバルフィルタリング手法はゲートウェイ(WebSocket)やハイブリッドアプリケーション(反応自機)では正常に機能しない.
import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter,
    },
  ],
})
export class AppModule {}
これを作成すると、「userGlobalFilters」と呼ばれるモジュールに含まれない場所で生成され、DIの観点からは、上のコードのように直接入れることができる悪いコードです.
ただし、この場合、どのモジュールに登録してもグローバルフィルタが使用されます.providerに配列を置くことで多くのものを登録できます.

Catch Everything


@Catch()のみを使用する場合は、すべての場合に使用できます.
このとき,次のコードのように記述すれば,プラットフォームにかかわらず,どんな場合でもうまく動作する.
import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  constructor(private readonly httpAdapterHost: HttpAdapterHost) {}

  catch(exception: unknown, host: ArgumentsHost): void {
    // In certain situations `httpAdapter` might not be available in the
    // constructor method, thus we should resolve it here.
    const { httpAdapter } = this.httpAdapterHost;

    const ctx = host.switchToHttp();

    const httpStatus =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    const responseBody = {
      statusCode: httpStatus,
      timestamp: new Date().toISOString(),
      path: httpAdapter.getRequestUrl(ctx.getRequest()),
    };

    httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
  }
}
まず、このような方法でプラットフォームから独立することも可能です.
import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';

@Catch()
export class AllExceptionsFilter extends BaseExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    super.catch(exception, host);
  }
}
このようにして、デフォルトのglobal filterを使用して、さらに変更することができます.
BaseException Filterをmethod-scope、cscontroller-scopeに拡張しないでください.これにより、newにインスタンス化する必要はありません.
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const { httpAdapter } = app.get(HttpAdapterHost);
  app.useGlobalFilters(new AllExceptionsFilter(httpAdapter));

  await app.listen(3000);
}
bootstrap();
1つ目の方法で作られたプラットフォームから独立したものは、このような方法で処理することができます.