NestJs - 使用自定义过滤器和 @Catch(MongoError) 捕获 MongoDB 错误 [英] NestJs - Catching MongoDB errors with a custom filter and @Catch(MongoError)
问题描述
我正在使用 NestJS 通过 MongoDB 创建自定义 API.我有以下设置:
I'm using NestJS to create a custom API with MongoDB. I've got the following setup:
// users.controller.ts
@Post('sign-up')
@UseFilters(MongoExceptionFilter)
async signUp(@Body() createUserDto: CreateUserDto): Promise<any> {
return await this.userService.signUp(createUserDto).catch(error => {
throw new BadRequestException(error);
});
}
// user.service.ts
async signUp(createUserDto: CreateUserDto): Promise<User> {
const createUser = new this.userModel(createUserDto);
return await createUser.save();
}
// mongo-exception.filter.ts
import { ArgumentsHost,Catch, ConflictException, ExceptionFilter } from '@nestjs/common';
import { MongoError } from 'mongodb';
@Catch(MongoError)
export class MongoExceptionFilter implements ExceptionFilter {
catch(exception: MongoError, host: ArgumentsHost) {
console.log('>>>>>>>>>>>>>>>>>>>> exception: ', exception);
}
}
// package.json
"dependencies": {
"@nestjs/common": "^5.4.0",
"@nestjs/core": "^5.4.0",
"@nestjs/jwt": "^0.2.1",
"@nestjs/mongoose": "^5.2.2",
"@nestjs/passport": "^5.1.0",
"@nestjs/typeorm": "^5.2.2",
"fancy-log": "^1.3.3",
"mongoose": "^5.4.7",
"nestjs-config": "^1.3.0",
"passport": "^0.4.0",
"passport-http-bearer": "^1.0.1",
"passport-jwt": "^4.0.0",
"reflect-metadata": "^0.1.12",
"rimraf": "^2.6.2",
"rxjs": "^6.2.2",
"typeorm": "^0.2.12",
"typescript": "^3.0.1",
"util": "^0.11.1"
},
现在,每当我对/sign-up 路由进行 POST 调用时,应该在 user.service.ts
中调用 save()
.这一切都有效.接下来,当我再次发布/sign-up 路由时,它应该会触发 MongoDB 错误,因为具有相同电子邮件地址的用户已经存在(电子邮件地址是唯一的,因此是重复的键).当我在 .catch(err => ...);
中记录错误时,我看到错误被抛出,但问题是自定义 MongoExceptionFilter
.我不会触发 MongoError.当我将 @Catch()
留空时,它会触发但无法处理异常.
Now whenever I do a POST call to the /sign-up route, save()
should be called in the user.service.ts
. This all works. Next when I POST the /sign-up route another time it should trigger a MongoDB error since the user with the same email address is already (email address is unique and thus duplicate keys). I see the error is thrown when I just log the error in the .catch(err => ...);
, but the problem is the custom MongoExceptionFilter
. I won't trigger on the MongoError. When I leave the @Catch()
blank it does trigger but can't process the exception.
我做错了什么?由于我看到了这篇帖子并将其用作基础,我可以'似乎让它发挥作用.是 Mongoose 还是 NestJS 的更新,为什么这不再起作用了?
What am I doing wrong? Since I saw this post and used this as a foundation I can't seem to get it to work. Is it an update of Mongoose or NestJS why this isn't working anymore?
推荐答案
这是因为你把所有的错误都转换成BadRequestExceptions
,这样你的MongoExceptionFilter
就不用负责了;它检查 instanceof MongoError
,它为 BadRequestException
返回 false:
This is because you convert all errors to BadRequestExceptions
so that your MongoExceptionFilter
will not be responsible; it checks instanceof MongoError
which returns false for a BadRequestException
:
return await this.userService.signUp(createUserDto).catch(error => {
throw new BadRequestException(error);
});
这发生在异常过滤器运行之前;他们总是最后运行.
This happens before the exception filters are run; they always run last.
从控制器中删除 .catch()
.如果您真的想将所有其他异常转换为 BadRequestExceptions (400),那么您可以编写第二个异常过滤器,处理所有未被 MongoExceptionFilter 处理的异常:
Remove .catch()
from your controller. If you really want to transform all other exceptions to BadRequestExceptions (400), then you can write a second exception filter, that processes all exceptions not handled by the MongoExceptionFilter:
@Catch()
export class BadRequestFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
const response = host.switchToHttp().getResponse();
response.status(400).json({message: exception.message});
}
}
和
@Catch(MongoError)
export class MongoFilter implements ExceptionFilter {
catch(exception: MongoError, host: ArgumentsHost) {
const response = host.switchToHttp().getResponse();
if (exception.code === 11000) {
response.status(400).json({ message: 'User already exists.' });
} else {
response.status(500).json({ message: 'Internal error.' });
}
}
}
然后将两者都添加到您的控制器中(顺序很重要!):
Then add both to your controller (order is important!):
@UseFilters(BadRequestFilter, MongoFilter)
async signUp(@Body() createUserDto: CreateUserDto): Promise<any> {
这篇关于NestJs - 使用自定义过滤器和 @Catch(MongoError) 捕获 MongoDB 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!