While using NestJS to create API's I was wondering which is the best way to handle errors/exception. I have found two different approaches :
throw new Error()
, have the controller catch
them and then throw the appropriate kind of HttpException
( BadRequestException
, ForbiddenException
etc..)HttpException
.There are pros and cons to both approaches:
Error
for different reasons, how do I know from the controller which would be the corresponding kind of HttpException
to return?Http
related stuff in services just seems wrong.I was wondering, which one (if any) is the "nest js" way of doing it?
How do you handle this matter?
Let's assume your business logic throws an EntityNotFoundError
and you want to map it to a NotFoundException
.
For that, you can create an Interceptor
that transforms your errors:
@Injectable()
export class NotFoundInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// next.handle() is an Observable of the controller's result value
return next.handle()
.pipe(catchError(error => {
if (error instanceof EntityNotFoundError) {
throw new NotFoundException(error.message);
} else {
throw error;
}
}));
}
}
You can then use it by adding @UseInterceptors(NotFoundInterceptor)
to your controller's class or methods; or even as a global interceptor for all routes. Of course, you can also map multiple errors in one interceptor.
Try it out in this codesandbox .
You may want to bind services not only to HTTP interface, but also for GraphQL or any other interface. So it is better to cast business-logic level exceptions from services to Http-level exceptions (BadRequestException, ForbiddenException) in controllers.
In the simpliest way it could look like
import { BadRequestException, Injectable } from '@nestjs/common';
@Injectable()
export class HttpHelperService {
async transformExceptions(action: Promise<any>): Promise<any> {
try {
return await action;
} catch (error) {
if (error.name === 'QueryFailedError') {
if (/^duplicate key value violates unique constraint/.test(error.message)) {
throw new BadRequestException(error.detail);
} else if (/violates foreign key constraint/.test(error.message)) {
throw new BadRequestException(error.detail);
} else {
throw error;
}
} else {
throw error;
}
}
}
}
and then
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.