Пройдите проверку @IsInt() для типа запроса application/x-www-form-urlencoded

Когда я просмотрел документацию по Pipes, я заметил, что не могу сделать @IsInt() проверка правильности запроса application/x-www-form-urlencoded, потому что все значения, которые я передал, я получаю как строковые значения.

Мои данные запроса выглядят так введите описание изображения здесь

Мой DTO выглядит так

import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
    @IsString()
    readonly name: string;

    @IsInt()
    readonly age: number;

    @IsString()
    readonly breed: string;
}

Труба проверки содержит следующий код

import { PipeTransform, Pipe, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';

@Pipe()
export class ValidationPipe implements PipeTransform<any> {
    async transform(value, metadata: ArgumentMetadata) {
        const { metatype } = metadata;
        if (!metatype || !this.toValidate(metatype)) {
            return value;
        }
        const object = plainToClass(metatype, value);
        const errors = await validate(object);
        if (errors.length > 0) {
            throw new BadRequestException('Validation failed');
        }
        return value;
    }

    private toValidate(metatype): boolean {
        const types = [String, Boolean, Number, Array, Object];
        return !types.find((type) => metatype === type);
    }
}

Когда я отлаживал эту трубу, я заметил это состояние введите описание изображения здесь Куда:

  • value - значение тела запроса
  • объект - преобразован через значение класса-преобразователя
  • ошибки - объект ошибки

Как видите, ошибки говорят нам, что возраст должен быть целым числом.

Как я могу пройти @IsInt() проверка для заявки / x-www-form-urlencoded запроса?

Версии библиотек:

  • @ nestjs / общие @ 4.6.4
  • class-transformer@0.1.8
  • class-validator@0.8.1

PS: Я также создаю репозиторий, где вы можете запустить приложение для проверки ошибок. Обязательная ветка how-to-pass-int-validation

UPD: после внесения изменений в принятый ответ я столкнулся с проблемой, связанной с неправильным анализом данных в хранилище. Записанный пример

Можно ли разобраться? createCatDto или что мне нужно сделать, чтобы сохранить его с правильной структурой типа?

2 ответа

Решение

Все значения из application/x-www-form-urlencoded запрос всегда строки.

Итак, вы можете сделать следующее:

import { Transform } from 'class-transformer';
import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
  @IsString()
  readonly name: string;

  @Transform(value => Number.isNan(+value) ? 0 : +value) // this field will be parsed to integer when `plainToClass gets called`
  @IsInt()
  readonly age: number;

  @IsString()
  readonly breed: string;
}

Добавление @Type(() => Number) решило проблему для меня.

      import { Type } from 'class-transformer';
import { IsInt, IsNotEmpty } from 'class-validator';

@IsNotEmpty({ message: '' })
@Type(() => Number)
@IsInt({ message: '' })
project: number;
Другие вопросы по тегам