Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Route parameters, query and body

A request carries data in three places: in the address itself (/posts/5), in the query string after the question mark (/posts?page=2) and in the body — for example, JSON with a new post. NestJS has a parameter decorator for each place: you put it in front of a method argument, and the framework fills in the value.

A route parameter

A part of the address with a colon is a parameter. The @Param() decorator reads it by name:

// src/posts/posts.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
 
@Controller('posts')
export class PostsController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return `Post number ${id}`;
  }
}

Open http://localhost:3000/posts/5 — you will see "Post number 5". The value always arrives as a string, even if the address contains digits. The lesson about pipes shows how to turn it into a number.

There can be several parameters:

// src/posts/posts.controller.ts
@Get(':postId/comments/:commentId')
findComment(
  @Param('postId') postId: string,
  @Param('commentId') commentId: string,
) {
  return `Comment ${commentId} on post ${postId}`;
}

The address /posts/5/comments/12 returns "Comment 12 on post 5".

The query string

Parameters after ? are read by @Query():

// src/posts/posts.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
 
@Controller('posts')
export class PostsController {
  @Get()
  findAll(@Query('page') page?: string, @Query('search') search?: string) {
    return { page: page ?? '1', search: search ?? '' };
  }
}

The address /posts?page=2&search=nest returns {"page":"2","search":"nest"}. If a parameter is missing from the address, the argument is undefined, so it is marked optional.

The request body

Data from the body of POST and PATCH requests comes through @Body(). NestJS parses JSON itself — nothing needs to be connected:

// src/posts/posts.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
 
@Controller('posts')
export class PostsController {
  @Post()
  create(@Body() body: { title: string; content: string }) {
    return { message: 'Post created', title: body.title };
  }
}

Send a request from the terminal:

curl -X POST http://localhost:3000/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"Hello, Nest","content":"First post"}'

The server answers {"message":"Post created","title":"Hello, Nest"}. If you pass a field name to @Body(), for example @Body('title'), you get only that field.

Summary

DecoratorWhere the data comes fromExample address
@Param('id')Part of the address/posts/5
@Query('page')Query string/posts?page=2
@Body()Request bodyPOST /posts with JSON
@Headers('user-agent')Headerany

Common mistake

The client sends JSON but forgets the Content-Type: application/json header. Then Express does not parse the body, and body turns out to be undefined or an empty object. If @Body() is empty, check this header first — in curl, Postman or in fetch() on the frontend.

Thanks for reading!

Donate to the site — we work hard for you.