How to make param required in NestJS?

Viewed 22979

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?

4 Answers

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> {
    ...
}

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.

Related