NestJS/GraphQL中如何为@Args参数加验证且不修改API规格?
问题描述
我有一个简单的GraphQL查询:
@Query(() => ProfileOutput) async profile(@Args('id') id: string) { return await this.profileFacade.findProfileById(input.id); }
我希望在此处为id参数应用class-validator的@IsMongoId()验证规则,但不想创建新的@InputType(这会改变API规格)。请问是否有办法在不修改前端查询定义的前提下实现该验证?
解决方案
1. 直接在参数上结合class-validator与ValidationPipe
NestJS的@Args装饰器支持直接搭配class-validator的验证规则,只要全局或局部启用ValidationPipe即可,完全不会改变API输入结构:
import { IsMongoId } from 'class-validator'; import { Args, Query } from '@nestjs/graphql'; @Query(() => ProfileOutput) async profile( @Args('id', { validate: true, type: () => String }) @IsMongoId() id: string ) { return await this.profileFacade.findProfileById(id); }
需要确保项目已配置ValidationPipe,可以在全局注册:
// main.ts import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); await app.listen(3000); } bootstrap();
前端依然只需传递id参数,API规格完全不变。
2. 封装自定义参数装饰器(复用验证逻辑)
如果需要在多个地方复用MongoID验证,可以封装一个自定义装饰器:
// src/decorators/mongo-id.decorator.ts import { applyDecorators } from '@nestjs/common'; import { Args } from '@nestjs/graphql'; import { IsMongoId } from 'class-validator'; export function MongoIdArg(name: string) { return applyDecorators( Args(name, { validate: true, type: () => String }), IsMongoId(), ); }
使用时直接替换@Args:
@Query(() => ProfileOutput) async profile(@MongoIdArg('id') id: string) { return await this.profileFacade.findProfileById(id); }
3. 手动验证(无需全局Pipe)
如果不想启用全局ValidationPipe,可以在方法内部手动调用验证逻辑:
import { validateOrReject } from 'class-validator'; import { BadRequestException } from '@nestjs/common'; @Query(() => ProfileOutput) async profile(@Args('id') id: string) { const tempValidationObj = { id }; try { await validateOrReject(tempValidationObj, { validationError: { target: false } }); } catch (errors) { throw new BadRequestException('无效的MongoDB ID'); } return await this.profileFacade.findProfileById(id); }
内容的提问来源于stack exchange,提问作者Moti
相关产品推荐
相关产品推荐

