【问题标题】:DTO not working for microservice, but working for apis directlyDTO不适用于微服务,而是直接用于api
【发布时间】:2019-11-15 07:27:27
【问题描述】:

我正在用 nestJS 开发 api 和微服务, 这是我的控制器功能

    @Post()
    @MessagePattern({ service: TRANSACTION_SERVICE, msg: 'create' })
    create( @Body() createTransactionDto: TransactionDto_create ) : Promise<Transaction>{
        return this.transactionsService.create(createTransactionDto)
    }

当我调用 post api 时,dto 验证工作正常,但是当我使用微服务验证调用它时不起作用,它会传递给服务而不会因错误而拒绝。 这是我的 DTO

import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class TransactionDto_create{
    @IsNotEmpty()
    action: string;

    // @IsString()
    readonly rec_id : string;

    @IsNotEmpty()
    readonly data : Object;

    extras : Object;
    // readonly extras2 : Object;
}

当我在没有操作参数的情况下调用 api 时,它显示需要执行错误操作,但是当我使用微服务调用它时

const 模式 = { service: TRANSACTION_SERVICE, msg: 'create' }; 常量数据 = {id: '5d1de5d787db5151903c80b9', extras:{'asdf':'dsf'}};

return this.client.send<number>(pattern, data)

它不会抛出错误并开始服务。 我还添加了 globalpipe 验证。

app.useGlobalPipes(new ValidationPipe({
    disableErrorMessages: false,  // set true to hide detailed error message
    whitelist: false,  // set true to strip params which are not in DTO
    transform: false // set true if you want DTO to convert params to DTO class by default its false
  }));

它将如何适用于 api 和微服务,因为我需要在一个地方并具有相同的功能,以便每个客户端都可以调用它。

【问题讨论】:

    标签: microservices nestjs class-validator


    【解决方案1】:

    我很想出去,假设你有main.ts 你有app.useGlobalPipes(new ValidationPipe()); 这条线。 From the documentation

    对于混合应用useGlobalPipes() 方法不会为网关和微服务设置管道。对于“标准”(非混合)微服务应用,useGlobalPipes() 会在全局范围内挂载管道。

    您可以改为从AppModule 全局绑定管道,或者您可以在需要通过ValidationPipe 验证的每条路由上使用@UsePipes() 装饰器

    More info on binding pipes here

    【讨论】:

    • 我试过这个,但问题是,即使验证有效,它也只会给出内部服务错误是对微服务的响应,它在服务中显示完全错误,但是在我调用的服务上,它在那里仅显示内部服务器错误响应。就像我从服务 B 调用服务 A 的函数一样,在服务 A 上它显示完全错误,如验证失败,但在服务 B 上它只显示内部服务器错误。我也需要完整的错误,以便该服务客户端现在应该是什么错误。
    • 这听起来像是传播错误并在您的情况下从服务 A 到服务 B 返回的问题。我建议设置一些 Filters 来帮助实现此功能
    • 我解决了,问题是,验证管道抛出异常对象,直接使用 api 时工作正常,但是微服务客户端的构建方式是,如果它的类型是 RpcException,它只接受整个错误对象,我刚刚添加了自定义验证管道,该管道扩展到验证管道,并将异常更改为 RpcException 现在它的工作。
    • @MuhammadAadilBanaras 方法可以工作,但它会消耗所有类验证器功能。我建议使用自定义过滤器来捕获 HttpException 并抛出 RpcException。
    【解决方案2】:

    ValidationPipe 抛出 HTTP BadRequestException,而代理客户端期望 RpcException。

    @Catch(HttpException)
    export class RpcValidationFilter implements ExceptionFilter {
        catch(exception: HttpException, host: ArgumentsHost) {
            return new RpcException(exception.getResponse())
        }
    }
    
    @UseFilters(new RpcValidationFilter())
    @MessagePattern('validate')
    async validate(
        @Payload(new ValidationPipe({ whitelist: true })) payload: SomeDTO,
    ) {
        // payload validates to SomeDto 
        . . .
    }
    

    【讨论】:

    • rpc可以在body中正确传递响应但是http状态码没有更新
    猜你喜欢
    • 2020-04-23
    • 2015-08-07
    • 1970-01-01
    • 2017-12-29
    • 2016-10-17
    • 1970-01-01
    • 2018-05-07
    • 2018-10-21
    • 1970-01-01
    相关资源
    最近更新 更多