Pass @IsInt() validation for application/x-www-form-urlencoded request type

Issue

When I went through Pipes documentation I noticed that I can’t make @IsInt() validation for application/x-www-form-urlencoded request correctly, cause all values which I passed I receive as string values.

My request data looks like this
enter image description here

My DTO looks like

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

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

    @IsInt()
    readonly age: number;

    @IsString()
    readonly breed: string;
}

Validation pipe contains next code

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);
    }
}

When I debug this pipe I noticed this state
enter image description here
Where:

  • value – request body value
  • object – transformed via class-transformer value
  • errors – error object

As you can see errors tell to us that age must be an integer number.

How can I pass @IsInt() validation for application/x-www-form-urlencoded request?

Libraries versions:

  • @nestjs/common@4.6.4
  • class-transformer@0.1.8
  • class-validator@0.8.1

P.S: I also create a repository where you can run application to test bug. Required branch how-to-pass-int-validation

UPD: after making changes from accepted answer I faced with problem that I put wrong parsed data to storage. Recorded example

Is it possible to get well parsed createCatDto or what I need to do to save it with correct type structure?

Solution

All values from a application/x-www-form-urlencoded request are always strings.

So, you could do the following:

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;
}

Answered By – Chanlito

Answer Checked By – Terry (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.