DTO 不适用于微服务,但直接适用于 API



我正在 nestJS 中开发 apis & microservices, 这是我的控制器功能

@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 时,它显示需要错误操作,但是当我使用

常量模式 = { 服务: TRANSACTION_SERVICE, msg: 'create' }; const data = {id: '5d1de5d787db5151903c80b9', extras:{'asdf':'dsf'}};

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

它不会抛出错误并投入使用。 我还添加了全局管道验证。

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 和微服务,因为我需要在一个地方使用相同的功能,以便可以根据客户端调用它。

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 
. . .
}

据我了解,useGlobalPipes适用于api,但不适用于微服务。 这背后的原因是,嵌套微服务是一个混合应用程序,它有一些限制。请参阅以下第1段。

默认情况下,混合应用程序不会继承为主(基于 HTTP)应用程序配置的全局管道、拦截器、防护和过滤器。若要从主应用程序继承这些配置属性,请在 connectMicroservice() 调用的第二个参数(可选选项对象)中设置 inheritAppConfig 属性。

请参考此巢官方文档

因此,您需要在connectMicroservice()方法中添加inheritAppConfig选项。

const microservice = app.connectMicroservice(
{
transport: Transport.TCP,
},
{ inheritAppConfig: true },
);

它对我有用!

我要出去走,假设你main.ts你有app.useGlobalPipes(new ValidationPipe());线。从文档

对于混合应用useGlobalPipes()方法不会为网关和微服务设置管道。对于"标准"(非混合)微服务应用,useGlobalPipes()会全局安装管道。

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

有关绑定管道的更多信息,请单击此处

最新更新