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;
}
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',
};