是否可以验证单个路由参数?

时间:2019-03-27 19:24:58

标签: javascript node.js typescript nestjs class-validator

假设我有以下路线:

companies/{companyId}/departments/{departmentId}/employees

是否可以分别验证两个资源ID(companyIddepartmentId)?我已经尝试过追踪,但是没有用。

class ResourceId {
  @IsNumberString()
  @StringNumberRange(...) // my custom validator
  id: number;
}

@Get(':companyId/departments/:departmentId/employees')
getEmployees(
  @Param('companyId') companyId: ResourceId,
  @Param('departmentId') departmentId: ResourceId,
) {}

在多种情况下,单个路径中有多个参数。我不想为每条路线创建单独的验证类。有没有其他方法可以解决这个问题?

1 个答案:

答案 0 :(得分:1)

问题是您在此处输入了纯字符串。为了使用class-validator进行验证,您必须实例化一个类,对于您的情况ResourceId。内置的ValidationPipe期望值是{id: '123'}而不是'123'能够自动转换它。但是您可以轻松创建自己的验证管道,从而完成此额外的转换。

export class ParamValidationPipe implements PipeTransform {
  async transform(value, metadata: ArgumentMetadata) {
    if (metadata.type === 'param') {
      // This is the relevant part: value -> { id: value }
      const valueInstance = plainToClass(metadata.metatype, { id: value });
      const validationErrors = await validate(valueInstance);
      if (validationErrors.length > 0) {
        throw new BadRequestException(validationErrors, 'Invalid route param');
      }
      return valueInstance;
    } else {
      return value;
    }
  }
}

然后可以在控制器上使用它:

@UsePipes(ParamValidationPipe)
@Get(':companyId/departments/:departmentId/employees')
getEmployees(
  @Param('companyId') companyId: ResourceId,
  @Param('departmentId') departmentId: ResourceId,
) {
  return `id1: ${companyId.id}, id2: ${departmentId.id}`;
}