Можно ли проверить один параметр маршрута?

Допустим, у меня есть следующий маршрут:

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

Можно ли проверить оба идентификатора ресурса (companyId, departmentId) по отдельности? Я пытался следовать, но это не работает.

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

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

У меня есть несколько случаев, когда в одном маршруте более одного параметра. Я не хотел бы создавать отдельный класс проверки для каждого маршрута. Есть ли способ решить эту проблему по-другому?

2 ответа

По состоянию на 2022 год в документах NestJS говорится, что можно проверить параметры маршрута с помощью встроенного канала проверки.

В контроллере:

      @Get(':id')
findOne(@Param() params: FindOneParams) {
  return 'This action returns a user';
}

Класс проверки:

      import { IsNumberString } from 'class-validator';

export class FindOneParams {
  @IsNumberString()
  id: number;
}

Ссылка: https://docs.nestjs.com/techniques/validation#auto-validation

Проблема в том, что у вас есть простая строка здесь. Для проверки с 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}`;
}
Другие вопросы по тегам