javascript - NestJS:如何在自定义验证器中同时访问 Body 和 Param?
问题描述
我有一个场景,我需要参数和正文中的值来执行自定义验证。例如,我有一条/:photoId/tag
为照片添加标签的路线。
但是,在向照片添加标签之前,它必须验证是否已经存在与照片同名的标签。
我的控制器中有以下路线:
@Post(':photoId/tag')
@UsePipes(new ValidationPipe())
async addTag(
@Param() params: AddTagParams,
@Body() addTagDto: AddTagDto
) {
// ...
}
由于:photoId
作为参数tag
提供并且在请求正文中提供了,因此它们无法在自定义验证器中相互访问,我无法使用这两条信息来检查数据库:
export class IsPhotoTagExistValidator implements ValidatorConstraintInterface {
async validate(val: any, args: ValidationArguments) {
// supposed to check whether a tag of the same name already exists on photo
// val only has the value of photoId but not the name of the tag from AddTagDto in Body
}
}
export class AddTagParams{
@IsInt()
@Validate(IsPhotoTagExistValidator) // this doesn't work because IsPhotoTagExistValidator can't access tag in AddTagDto
photoId: number
}
export class AddTagDto{
@IsString()
tag: string
}
如上例所示,val
inIsPhotoTagExistValidator
只是photoId
. 但是我需要photoId
in Param 和tag
Body 中的 name 来检查特定对象是否photoId
已经具有 that tag
。
我应该如何在自定义验证器函数中同时访问 Body 和 Param?如果没有,我应该如何解决这个问题?
解决方案
到目前为止,我发现的唯一解决方案来自此评论https://github.com/nestjs/nest/issues/528#issuecomment-497020970
context.interceptor.ts
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'
import { Observable } from 'rxjs'
/**
* Injects request data into the context, so that the ValidationPipe can use it.
*/
@Injectable()
export class ContextInterceptor implements NestInterceptor {
intercept(
context: ExecutionContext,
next: CallHandler
): Observable<any> {
const request = context.switchToHttp().getRequest();
request.body.context = {
params: request.params,
query: request.query,
user: request.user,
};
return next.handle()
}
}
main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new ContextInterceptor());
// ...
}
如果您{whitelist: true}
在ValidationPipe
参数中使用,则需要context
在您的 Dto 对象中允许。
这可以通过扩展这样的 Dto 来完成:
context-aware.dto.ts
import { Allow } from 'class-validator';
export class ContextAwareDto {
@Allow()
context?: {
params: any,
query: any,
user: any,
}
}
在此之后,您将能够在通过自定义验证器验证正文时访问请求数据validationArguments.object.context
您可以在验证参数或查询时轻松调整上述内容以访问上下文,尽管我发现仅在正文验证期间拥有此内容就足够了。
推荐阅读
- mongodb - 'mongod' 命令不起作用,尽管我将它添加到 PATH
- css - bootstrap 4.3 nav-item selected 无法使底部边框透明
- vuejs2 - Vue2 Mutations 为什么只提交第一个元素?
- gcc - AIX7.2 服务器上的 Apache Thrift 安装失败
- python - AttributeError:“NoneType”对象没有属性“hero_first”
- c - 在 C 中读取文本文件时出现循环问题
- macos - 如何在 swiftUI 生命周期中为三列视图添加工具栏分隔符
- c# - 如何通过拖放将列表视图项从一个列表移动到另一个列表?UWP C#
- python - 如何解决错误只能将str(不是“字节”)连接到str
- android - 从 iOS 访问谷歌智能锁密码