@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const res = ctx.getResponse<Response>();
const req = ctx.getRequest<Request>();
const status = exception instanceof HttpException ? exception.getStatus() : 500;
const message = exception instanceof HttpException ? exception.message : "Internal server error";
res.status(status).json({ statusCode: status, message, path: req.url, timestamp: new Date().toISOString() });
}
}
Write a class that implements ExceptionFilter, catch every error with @Catch(), and send the response yourself.
The filter:
- It implements the
catch(exception, host)method. @Catch()with no arguments catches every exception.@Catch(HttpException)would catch only that class and its subclasses.ArgumentsHostgives access to the underlying request and response throughswitchToHttp().- The filter builds the error body and sends the response itself.
Registering it. There are two ways:
- In
main.ts:app.useGlobalFilters(new AllExceptionsFilter()). - In a module:
{ provide: APP_FILTER, useClass: AllExceptionsFilter }. With this way, the filter can inject services, like a logger.
To stay independent of the HTTP platform (Express or Fastify), inject HttpAdapterHost. Reply through the adapter instead of calling Express methods.
Log unknown errors on the server. Don't send their messages to the client, because they can leak internal details.
- Implement
ExceptionFilter.catch(exception, host). @Catch()with no arguments catches every exception.ArgumentsHost.switchToHttp()gives the request and response.- Register with
useGlobalFilters, or withAPP_FILTERto get DI. - Don't send internal error messages to the client.
Read more