我有一个CreateFolderDto
类,其中有两个只读字段:
export class CreateFolderDto {
public readonly name: string
public readonly user_id: number
}
我有一个控制器,该控制器是:
@UseGuards(AuthGuard('jwt'))
@Post()
public create(@Request() req, @Body() createFolderDto: CreateFolderDto) {
return this.folderService.create(createFolderDto)
}
发送到我的控制器的请求是一个很好的请求,我只发送name
格式的json
,并且标头中带有accessToken
。 accessToken
允许我通过user_id
从请求中获得req.user.id
。
DTO字段user_id
不会自动填充。我想自动填写。
这是一种自动填充createFolderDto.user_id
变量的方法吗?
答案 0 :(得分:1)
@Body
仅将实际的请求正文包装到CreateFolderDto
类的实例中。由于到达端点的正文没有这样的字段,因此您需要手动添加它。
通常,可以使用DTO的自定义构造函数添加聚合字段:
export class CreateFolderDto {
public readonly name: string
public readonly session_uuid: string
constructor(bodyValue: any = {}) {
this.name = bodyValue.name
this.session_uuid = generateUuid()
}
}
但是在您的情况下,user
本身附加到request
上,因此我相信您有以下选择:
检出将user
附加到自身的代码。如果您使用的是NestJS文档中介绍的JWT Auth,则不能采用这种方式。
您可以编写自定义拦截器:
Injectable()
export class ExtendBodyWithUserId implements NestInterceptor {
async intercept(context: ExecutionContext, next: CallHandler) {
const request = context.switchToHttp().getRequest()
request.body.user_id = request.user
return next.handle()
}
}
// usage
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(ExtendBodyWithUserId)
@Post()
public create(@Request() req, @Body() createFolderDto: CreateFolderDto) {
return this.folderService.create(createFolderDto)
}
最后但并非最不重要的一些个人建议。考虑一下您将使用这个拦截器作为扩展的程度,因为过多的“ extras”都会使代码库膨胀。
我建议将folderService
签名更改为:
create(createFolderDto: CreateFolderDto, user: User)
,其中文件夹dto仅具有名称,而没有与用户相关的条目。您保持一致,分离和明确的意图。在create
的实现中,您可以进一步传递user.id
。
按照这种方式,您不必编写自定义拦截器。
选择您的方式,并确保代码库中的一致性与您同在!