英文:
Exceptions in microservices on nestjs
问题
我有一个微服务应用程序,一个 API 网关和一个服务。RabbitMQ
用作消息代理。我意识到在服务中,需要使用带有消息和状态码的 RpcException
,而不是 HttpException
。但是,当在 DTO
中验证数据时使用 ValidationPipe
时,我从 API 网关得到了 500 的 statusCode
。因为在底层它会抛出一个 BadRequestException
。老实说,我不太明白我需要做什么来将此异常转换为 rpc 格式,或者我可能需要做其他事情。也许需要一些 exceptionFilter
,但我不知道该如何做。
API 网关
@Controller()
export class ApiGateway {
constructor(
@Inject('AUTH_SERVICE') private authService: ClientProxy,
) {}
@Post('auth/register')
async register(
@Body('email') email: string,
@Body('password') password: string | number,
) {
return this.authService.send({ cmd: 'register' }, { email, password });
}
}
main.ts auth
async function bootstrap() {
const app = await NestFactory.create(AuthModule);
const configService = app.get(ConfigService);
const rmqService = app.get(RmqService);
const queue = configService.get('RABBITMQ_AUTH_QUEUE');
app.connectMicroservice(rmqService.getOptions(queue));
await app.startAllMicroservices();
}
bootstrap();
auth.controller
@Controller()
export class AuthController {
constructor(
private readonly authService: AuthService,
private readonly rmqService: RmqService,
) {}
@MessagePattern({ cmd: 'register' })
async register(@Ctx() ctx: RmqContext, @Payload() newUser: UserDto) {
this.rmqService.acknowledgeMessage(ctx);
return this.authService.register(newUser);
}
}
UserDto
@UsePipes(new ValidationPipe({ whitelist: true }))
export class UserDto {
@IsEmail()
email: string;
@IsString()
@IsNotEmpty()
password: string;
}
英文:
I have a microservice application, an api gateway and a service. RabbitMQ
is used as a message broker. I realized that in the service you need to use RpcException
with message and statusCode instead of HttpException
. But I ran into difficulty when using ValidationPipe
when validating data in DTO
, I get 500 statusCode
from api gateway. Because under the hood it throws a BadRequestException
. I honestly do not understand what I need to do to convert this exception to the rpc format, or maybe I need to do something else. Perhaps some kind of exceptionFilter
is needed, but I do not understand how to do it.
api gateway
@Controller()
export class ApiGateway {
constructor(
@Inject('AUTH_SERVICE') private authService: ClientProxy,
) {}
@Post('auth/register')
async register(
@Body('email') email: string,
@Body('password') password: string | number,
) {
return this.authService.send({ cmd: 'register' }, { email, password });
}
}
main.ts auth
async function bootstrap() {
const app = await NestFactory.create(AuthModule);
const configService = app.get(ConfigService);
const rmqService = app.get(RmqService);
const queue = configService.get('RABBITMQ_AUTH_QUEUE');
app.connectMicroservice(rmqService.getOptions(queue));
await app.startAllMicroservices();
}
bootstrap();
auth.controller
@Controller()
export class AuthController {
constructor(
private readonly authService: AuthService,
private readonly rmqService: RmqService,
) {}
@MessagePattern({ cmd: 'register' })
async register(@Ctx() ctx: RmqContext, @Payload() newUser: UserDto) {
this.rmqService.acknowledgeMessage(ctx);
return this.authService.register(newUser);
}
}
UserDto
@UsePipes(new ValidationPipe({ whitelist: true }))
export class UserDto {
@IsEmail()
email: string;
@IsString()
@IsNotEmpty()
password: string;
}
答案1
得分: 0
export const VALIDATION_PIPE_OPTIONS = {
transform: true,
whitelist: true,
exceptionFactory: (errors) => {
return new RpcException({
message: validationErrorsConversion(errors),
statusCode: 400,
});
},
};
export function validationErrorsConversion(arr) {
const result = [];
arr.forEach((obj) => {
const { property, constraints } = obj;
const values = Object.keys(constraints).map(
(key) => VALIDATION_ERRORS_CONST[key] || constraints[key],
);
result.push({
[property]: values,
});
});
return result;
}
export const VALIDATION_ERRORS_CONST = {
isEmail: 'Is not email',
isString: 'It should be a string',
};
英文:
I managed to override HttpException
with RpcException
. I also redefined the form in which I will receive validation error messages, maybe it will be useful to someone
export const VALIDATION_PIPE_OPTIONS = {
transform: true,
whitelist: true,
exceptionFactory: (errors) => {
return new RpcException({
message: validationErrorsConversion(errors),
statusCode: 400,
});
},
};
export function validationErrorsConversion(arr) {
const result = [];
arr.forEach((obj) => {
const { property, constraints } = obj;
const values = Object.keys(constraints).map(
(key) => VALIDATION_ERRORS_CONST[key] || constraints[key],
);
result.push({
[property]: values,
});
});
return result;
}
export const VALIDATION_ERRORS_CONST = {
isEmail: 'Is not email',
isString: 'It should be a string',
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论