infodev
infodev

Reputation: 5235

How to make param required in NestJS?

I would like to make my route Query parameter required. If it is missing I expect it to throw 404 HTTP error.

@Controller('')
export class AppController {
  constructor() {}
  @Get('/businessdata/messages')
  public async getAllMessages(
    @Query('startDate', ValidateDate) startDate: string,
    @Query('endDate', ValidateDate) endDate: string,
  ): Promise<string> {
   ...
  }
}

I'm using NestJs pipes to determine if a parameter is valid, but not if it exists And I'm not sure that Pipes are made for that.

So how can I check in NestJS if my param exists if not throw an error?

Upvotes: 15

Views: 35164

Answers (5)

benterris
benterris

Reputation: 851

You can define a DTO like you would for a @Body, instead of listing all the query params in the function args, like so:

@Get('/businessdata/messages')
public async getAllMessages(
  @Query() getAllMessagesDto: GetAllMessagesDto
): Promise<string> {
  console.log(getAllMessagesDto.endDate) // etc
}

And define your DTO with your requirements like so:

import { IsNotEmpty } from 'class-validator';

export class GetAllMessagesDto {
  @IsNotEmpty()
  startDate: Date;
  
  @IsNotEmpty()
  endDate: Date;
}

You can check this doc to see details about how to add validators to your DTO, and in your case don't forget to add forbidNonWhitelisted if you want to refuse values that are not expected.

Upvotes: 2

Hnennyi Andrii
Hnennyi Andrii

Reputation: 161

NestJS does not provide a decorator (like @Query) that detects undefined value in request.query[key].

You can write custom decorator for that:

import { createParamDecorator, ExecutionContext, BadRequestException } from '@nestjs/common'

export const QueryRequired = createParamDecorator(
  (key: string, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest()

    const value = request.query[key]

    if (value === undefined) {
      throw new BadRequestException(`Missing required query param: '${key}'`)
    }

    return value
  }
)

Then use @QueryRequired decorator as you would use @Query:

@Get()
async someMethod(@QueryRequired('requiredParam') requiredParam: string): Promise<any> {
    ...
}

Upvotes: 14

Philou
Philou

Reputation: 123

In addition to Phi's answer, you can combine the use of class-validator with the following global validation pipe:

app.useGlobalPipes(
    new ValidationPipe({
      /*
            If set to true, instead of stripping non-whitelisted 
            properties validator will throw an exception.
      */
      forbidNonWhitelisted: true,
      /*
            If set to true, validator will strip validated (returned) 
            object of any properties that do not use any validation decorators.
      */
      whitelist: true,
    }),
  );

I use this in order to only allow parameters defined in the DTO class so that it will throw an error when unknown parameters are sent with the request!

In Phie's example, a post request with a body like {password: 'mypassword'} will pass the validation when {password: 'mypassword', other: 'reject me!'} won't.

Upvotes: 2

Phie
Phie

Reputation: 413

Use class-validator. Pipes are definitely made for that !

Example : create-user.dto.ts

import { IsNotEmpty } from 'class-validator';

export class CreateUserDto {
   @IsNotEmpty()
   password: string;
}

For more information see class-validator documentation : https://github.com/typestack/class-validator

And NestJS Pipes & Validation documentation : https://docs.nestjs.com/pipes https://docs.nestjs.com/techniques/validation

Upvotes: 16

jkchao
jkchao

Reputation: 403

There hava a easy way to valide you parameter, https://docs.nestjs.com/techniques/validation

Upvotes: 4

Related Questions