Exception filters

Exception filters

Nest 에는 애플리케이션 전체에서 처리되지 않은 모든 예외를 처리하는 레이어가 내장되어 있다. 처리 되지 않은 예외가 여기에서 잡힌다.

기본적으로 이 작업은 HttpException 유형의 예외를 처리하는 내장 전역 예외 필터에 의해 수행된다.

예외가 인식되지 않는 경우(HttpException 도 아니고, HttpException에서 상속한 클래스도 아님) 기본 제공 예외 필터는 다음과 같은 기본 JSON 응답을 새성한다.

1
2
3
4
{
"statusCode": 500,
"message": "Internal server error"
}

http-erros 라이브러를 사용한다. 기본적으로 statusCode와 message 가 채워져서 응답으로 보내진다.

Throwing standard exceptions

Nest 는 HttpException class 를 내장해서 사용한다. 컨틀롤러에서 에러를 발생시키는 예시 코드를 만들어 보자.

1
2
3
4
@Get()
async findAll() {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}

클라이언트가 해당 엔드포인트를 호출하면 다음 json을 반환한다.

1
2
3
4
{
"statusCode": 403,
"message": "Forbidden"
}

HttpException 은 response 와 status 를 받는데 response 는 string이나 객체가 올 수 있고, status 는 HTTP status code 를 사용한다. response에 객체를 넘겨주면, serialize 해서 반환해 준다.

1
2
3
4
5
6
7
@Get()
async findAll() {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, HttpStatus.FORBIDDEN);
}

반환하는 JSON :

1
2
3
4
{
"status": 403,
"error": "This is a custom message"
}

Custom exceptions

대부분의 경우 custom exceptions를 사용할 일이 없지만 사용하고 싶다면 HttpException을 상속하는 예외 클래스를 커스텀 할 수 있다.

1
2
3
4
5
export class ForbiddenException extends HttpException {
constructor() {
super('Forbidden', HttpStatus.FORBIDDEN);
}
}

HttpException 을 상속하였기 때문에 동일하게 동작하여 동일하게 사용할 수 있다.

1
2
3
4
@Get()
async findAll() {
throw new ForbiddenException();
}

Built-in HTTP exceptions

Nest는 기본 ThhpException에서 상속되는 일련의 표준 예외를 제공한다.

Exception filters

Exception filters 는 에러에대한 컨트롤을 위해서 디자인되었다. 다음은 HttpException 인스턴스 예외를 포착하고 이데 대응하는 사용자 응답을 구현하는 예외 필터를 만들어 본다.

이를 위해서는 Request와 Response가 필요하고 Request에서 url 을 가져와 logging을 만들고 Response.json() 메서드를 사용하여 응답되는 데이터를 직접 제어해 본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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,
});
}
}

모든 예외 필터는 ExceptionFilter 제너릭으로 구현해야 한다. catch에 exception type으로 제너링 타입을 사용한다. catch(exception: T, host: ArgumetnHost)