在 NestJS 中的微服务中的异常

huangapple go评论71阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年7月10日 15:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76651600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定