0% found this document useful (0 votes)
6 views19 pages

Controllers - NestJS - A Progressive Node - Js Framework

The document provides an overview of controllers in NestJS, which are responsible for handling incoming requests and sending responses. It explains how to create controllers using classes and decorators, manage routing, and handle various HTTP methods. Additionally, it covers advanced features like route parameters, sub-domain routing, and response manipulation techniques.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views19 pages

Controllers - NestJS - A Progressive Node - Js Framework

The document provides an overview of controllers in NestJS, which are responsible for handling incoming requests and sending responses. It explains how to create controllers using classes and decorators, manage routing, and handle various HTTP methods. Additionally, it covers advanced features like route parameters, sub-domain routing, and response manipulation techniques.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

23:18 6/7/25 Controllers | NestJS - A progressive Node.

js framework

dark_mode

https://docs.nestjs.com/controllers 1/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

Controllers
Controllers are responsible for handling incoming requests and sending responses back to the client.

A controller's purpose is to handle specific requests for the application. The routing mechanism determines which
controller will handle each request. Often, a controller has multiple routes, and each route can perform a different
action.

To create a basic controller, we use classes and decorators. Decorators link classes with the necessary metadata,
allowing Nest to create a routing map that connects requests to their corresponding controllers.

HINT
To quickly create a CRUD controller with built-in validation, you can use the CLI's CRUD generator: nest g
resource [name] .

Routing
In the following example, we’ll use the @Controller() decorator, which is required to define a basic controller.
We'll specify an optional route path prefix of cats . Using a path prefix in the @Controller() decorator helps us
group related routes together and reduces repetitive code. For example, if we want to group routes that manage
interactions with a cat entity under the /cats path, we can specify the cats path prefix in the @Controller()
decorator. This way, we don't need to repeat that portion of the path for each route in the file.

https://docs.nestjs.com/controllers 2/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

cats.controller.ts JS

import { Controller, Get } from '@nestjs/common'; content_copy

@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}

HINT
To create a controller using the CLI, simply execute the $ nest g controller [name] command.

The @Get() HTTP request method decorator placed before the findAll() method tells Nest to create a handler
for a specific endpoint for HTTP requests. This endpoint is defined by the HTTP request method (GET in this case)
and the route path. So, what is the route path? The route path for a handler is determined by combining the
(optional) prefix declared for the controller with any path specified in the method's decorator. Since we've set a
prefix ( cats ) for every route and haven't added any specific path in the method decorator, Nest will map GET
/cats requests to this handler.

As mentioned, the route path includes both the optional controller path prefix and any path string specified in the
method's decorator. For example, if the controller prefix is cats and the method decorator is @Get('breed') , the
resulting route will be GET /cats/breed .

In our example above, when a GET request is made to this endpoint, Nest routes the request to the user-defined
findAll() method. Note that the method name we choose here is entirely arbitrary. While we must declare a
method to bind the route to, Nest doesn’t attach any specific significance to the method name.

This method will return a 200 status code along with the associated response, which in this case is just a string. Why
does this happen? To explain, we first need to introduce the concept that Nest uses two different options for
manipulating responses:

Standard Using this built-in method, when a request handler returns a JavaScript object
(recommended) or array, it will automatically be serialized to JSON. When it returns a
JavaScript primitive type (e.g., string , number , boolean ), however, Nest
https://docs.nestjs.com/controllers 3/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

will send just the value without attempting to serialize it. This makes response
handling simple: just return the value, and Nest takes care of the rest.

Furthermore, the response's status code is always 200 by default, except for
POST requests which use 201. We can easily change this behavior by adding
the @HttpCode(...) decorator at a handler-level (see Status codes).

Library-specific We can use the library-specific (e.g., Express) response object, which can be
injected using the @Res() decorator in the method handler signature (e.g.,
findAll(@Res() response) ). With this approach, you have the ability to use
the native response handling methods exposed by that object. For example,
with Express, you can construct responses using code like
response.status(200).send() .

WARNING
Nest detects when the handler is using either @Res() or @Next() , indicating you have chosen the library-
specific option. If both approaches are used at the same time, the Standard approach is automatically
disabled for this single route and will no longer work as expected. To use both approaches at the same time
(for example, by injecting the response object to only set cookies/headers but still leave the rest to the
framework), you must set the passthrough option to true in the @Res({ passthrough: true })
decorator.

Explore your graph with NestJS


Devtools
Graph visualizer Interactive playground

Routes navigator CI/CD integration

SIGN UP

Request object
https://docs.nestjs.com/controllers 4/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

Handlers often need access to the client’s request details. Nest provides access to the request object from the
underlying platform (Express by default). You can access the request object by instructing Nest to inject it using the
@Req() decorator in the handler’s signature.

cats.controller.ts JS

import { Controller, Get, Req } from '@nestjs/common'; content_copy


import { Request } from 'express';

@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: Request): string {
return 'This action returns all cats';
}
}

HINT
To take advantage of express typings (like in the request: Request parameter example above), make sure
to install the @types/express package.

The request object represents the HTTP request and contains properties for the query string, parameters, HTTP
headers, and body (read more here). In most cases, you don't need to manually access these properties. Instead,
you can use dedicated decorators like @Body() or @Query() , which are available out of the box. Below is a list of
the provided decorators and the corresponding platform-specific objects they represent.

@Request(), @Req() req

@Response(), @Res() * res

@Next() next

@Session() req.session

https://docs.nestjs.com/controllers 5/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

@Param(key?: string) req.params / req.params[key]

@Body(key?: string) req.body / req.body[key]

@Query(key?: string) req.query / req.query[key]

@Headers(name?: string) req.headers / req.headers[name]

@Ip() req.ip

@HostParam() req.hosts

* For compatibility with typings across underlying HTTP platforms (e.g., Express and Fastify), Nest provides @Res()

and @Response() decorators. @Res() is simply an alias for @Response() . Both directly expose the underlying
native platform response object interface. When using them, you should also import the typings for the
underlying library (e.g., @types/express ) to take full advantage. Note that when you inject either @Res() or
@Response() in a method handler, you put Nest into Library-specific mode for that handler, and you become
responsible for managing the response. When doing so, you must issue some kind of response by making a call on
the response object (e.g., res.json(...) or res.send(...) ), or the HTTP server will hang.

HINT
To learn how to create your own custom decorators, visit this chapter.

Resources
Earlier, we defined an endpoint to fetch the cats resource (GET route). We'll typically also want to provide an
endpoint that creates new records. For this, let's create the POST handler:

cats.controller.ts JS

import { Controller, Get, Post } from '@nestjs/common'; content_copy

https://docs.nestjs.com/controllers 6/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

@Controller('cats')
export class CatsController {
@Post()
create(): string {
return 'This action adds a new cat';
}

@Get()
findAll(): string {
return 'This action returns all cats';
}
}

It's that simple. Nest provides decorators for all of the standard HTTP methods: @Get() , @Post() , @Put() ,
@Delete() , @Patch() , @Options() , and @Head() . In addition, @All() defines an endpoint that handles all of
them.

Route wildcards
Pattern-based routes are also supported in NestJS. For example, the asterisk ( * ) can be used as a wildcard to
match any combination of characters in a route at the end of a path. In the following example, the findAll()
method will be executed for any route that starts with abcd/ , regardless of the number of characters that follow.

@Get('abcd/*') content_copy
findAll() {
return 'This route uses a wildcard';
}

The 'abcd/*' route path will match abcd/ , abcd/123 , abcd/abc , and so on. The hyphen ( - ) and the dot ( . )
are interpreted literally by string-based paths.

This approach works on both Express and Fastify. However, with the latest release of Express (v5), the routing
system has become more strict. In pure Express, you must use a named wildcard to make the route work—for
example, abcd/*splat , where splat is simply the name of the wildcard parameter and has no special meaning.
You can name it anything you like. That said, since Nest provides a compatibility layer for Express, you can still use
the asterisk ( * ) as a wildcard.

When it comes to asterisks used in the middle of a route, Express requires named wildcards (e.g., ab{*splat}cd ),
https://docs.nestjs.com/controllers 7/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

while Fastify does not support them at all.

Status code
As mentioned, the default status code for responses is always 200, except for POST requests, which default to 201.
You can easily change this behavior by using the @HttpCode(...) decorator at the handler level.

@Post() content_copy
@HttpCode(204)
create() {
return 'This action adds a new cat';
}

HINT
Import HttpCode from the @nestjs/common package.

Often, your status code isn't static but depends on various factors. In that case, you can use a library-specific
response (inject using @Res() ) object (or, in case of an error, throw an exception).

Response headers
To specify a custom response header, you can either use a @Header() decorator or a library-specific response
object (and call res.header() directly).

@Post() content_copy
@Header('Cache-Control', 'no-store')
create() {
return 'This action adds a new cat';
}

HINT
Import Header from the @nestjs/common package.

https://docs.nestjs.com/controllers 8/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

Redirection
To redirect a response to a specific URL, you can either use a @Redirect() decorator or a library-specific response
object (and call res.redirect() directly).

@Redirect() takes two arguments, url and statusCode , both are optional. The default value of statusCode is
302 ( Found ) if omitted.

@Get() content_copy
@Redirect('https://nestjs.com', 301)

HINT
Sometimes you may want to determine the HTTP status code or the redirect URL dynamically. Do this by
returning an object following the HttpRedirectResponse interface (from @nestjs/common ).

Returned values will override any arguments passed to the @Redirect() decorator. For example:

@Get('docs') content_copy
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}

Route parameters
Routes with static paths won’t work when you need to accept dynamic data as part of the request (e.g., GET
/cats/1 to get the cat with id 1 ). To define routes with parameters, you can add route parameter tokens in the
route path to capture the dynamic values from the URL. The route parameter token in the @Get() decorator
example below illustrates this approach. These route parameters can then be accessed using the @Param()
decorator, which should be added to the method signature.

HINT
https://docs.nestjs.com/controllers 9/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
HINT
Routes with parameters should be declared after any static paths. This prevents the parameterized paths
from intercepting traffic destined for the static paths.

JS

@Get(':id') content_copy
findOne(@Param() params: any): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}

The @Param() decorator is used to decorate a method parameter (in the example above, params ), making the
route parameters accessible as properties of that decorated method parameter inside the method. As shown in the
code, you can access the id parameter by referencing params.id . Alternatively, you can pass a specific
parameter token to the decorator and directly reference the route parameter by name within the method body.

HINT
Import Param from the @nestjs/common package.

JS

@Get(':id') content_copy
findOne(@Param('id') id: string): string {
return `This action returns a #${id} cat`;
}

Sub-domain routing
The @Controller decorator can take a host option to require that the HTTP host of the incoming requests
matches some specific value.

@Controller({ host: 'admin.example.com' }) content_copy


l Ad i C
https://docs.nestjs.com/controllers
ll { 10/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
export class AdminController {
@Get()
index(): string {
return 'Admin page';
}
}

WARNING
Since Fastify does not support nested routers, if you are using sub-domain routing, it is recommended to use
the default Express adapter instead.

Similar to a route path , the host option can use tokens to capture the dynamic value at that position in the host
name. The host parameter token in the @Controller() decorator example below demonstrates this usage. Host
parameters declared in this way can be accessed using the @HostParam() decorator, which should be added to the
method signature.

@Controller({ host: ':account.example.com' }) content_copy


export class AccountController {
@Get()
getInfo(@HostParam('account') account: string) {
return account;
}
}

State sharing
For developers coming from other programming languages, it might be surprising to learn that in Nest, nearly
everything is shared across incoming requests. This includes resources like the database connection pool, singleton
services with global state, and more. It's important to understand that Node.js doesn't use the request/response
Multi-Threaded Stateless Model, where each request is handled by a separate thread. As a result, using singleton
instances in Nest is completely safe for our applications.

That said, there are specific edge cases where having request-based lifetimes for controllers may be necessary.
Examples include per-request caching in GraphQL applications, request tracking, or implementing multi-tenancy.
You can learn more about controlling injection scopes here.

https://docs.nestjs.com/controllers 11/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
Asynchronicity
We love modern JavaScript, especially its emphasis on asynchronous data handling. That’s why Nest fully supports
async functions. Every async function must return a Promise , which allows you to return a deferred value that
Nest can resolve automatically. Here's an example:

cats.controller.ts JS

@Get() content_copy
async findAll(): Promise<any[]> {
return [];
}

This code is perfectly valid. But Nest takes it a step further by allowing route handlers to return RxJS observable
streams as well. Nest will handle the subscription internally and resolve the final emitted value once the stream
completes.

cats.controller.ts JS

@Get() content_copy
findAll(): Observable<any[]> {
return of([]);
}

Both approaches are valid, and you can choose the one that best suits your needs.

Request payloads
In our previous example, the POST route handler didn’t accept any client parameters. Let's fix that by adding the
@Body() decorator.

Before we proceed (if you're using TypeScript), we need to define the DTO (Data Transfer Object) schema. A DTO is
an object that specifies how data should be sent over the network. We could define the DTO schema using
TypeScript interfaces or simple classes. However, we recommend using classes here. Why? Classes are part of the
JavaScript ES6 standard, so they remain intact as real entities in the compiled JavaScript. In contrast, TypeScript
interfaces are removed during transpilation, meaning Nest can't reference them at runtime. This is important
because features like Pipes rely on having access to the metatype of variables at runtime, which is only possible
ih l
https://docs.nestjs.com/controllers 12/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
with classes.

Let's create the CreateCatDto class:

create-cat.dto.ts JS

export class CreateCatDto { content_copy


name: string;
age: number;
breed: string;
}

It has only three basic properties. Thereafter we can use the newly created DTO inside the CatsController :

cats.controller.ts JS

@Post() content_copy
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}

HINT
Our ValidationPipe can filter out properties that should not be received by the method handler. In this
case, we can whitelist the acceptable properties, and any property not included in the whitelist is
automatically stripped from the resulting object. In the CreateCatDto example, our whitelist is the name ,
age , and breed properties. Learn more here.

Query parameters
When handling query parameters in your routes, you can use the @Query() decorator to extract them from
incoming requests. Let's see how this works in practice.

Consider a route where we want to filter a list of cats based on query parameters like age and breed . First, define
the query parameters in the CatsController :

https://docs.nestjs.com/controllers 13/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

cats.controller.ts JS

@Get() content_copy
async findAll(@Query('age') age: number, @Query('breed') breed: string) {
return `This action returns all cats filtered by age: ${age} and breed: ${breed}`;
}

In this example, the @Query() decorator is used to extract the values of age and breed from the query string.
For example, a request to:

GET /cats?age=2&breed=Persian

would result in age being 2 and breed being Persian .

If your application requires handling more complex query parameters, such as nested objects or arrays:

?filter[where][name]=John&filter[where][age]=30
?item[]=1&item[]=2

you'll need to configure your HTTP adapter (Express or Fastify) to use an appropriate query parser. In Express, you
can use the extended parser, which allows for rich query objects:

const app = await NestFactory.create<NestExpressApplication>(AppModule); content_copy


app.set('query parser', 'extended');

In Fastify, you can use the querystringParser option:

const app = await NestFactory.create<NestFastifyApplication>( content_copy


AppModule,
new FastifyAdapter({
querystringParser: (str) => qs.parse(str),
https://docs.nestjs.com/controllers 14/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
que yst g a se : (st ) qs.pa se(st ),
}),
);

HINT
qs is a querystring parser that supports nesting and arrays. You can install it using npm install qs .

Handling errors
There's a separate chapter about handling errors (i.e., working with exceptions) here.

Full resource sample


Below is an example that demonstrates the use of several available decorators to create a basic controller. This
controller provides a few methods to access and manipulate internal data.

cats.controller.ts JS

import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';content_copy
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';

@Controller('cats')
export class CatsController {
@Post()
create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}

@Get()
findAll(@Query() query: ListAllEntities) {
return `This action returns all cats (limit: ${query.limit} items)`;
}

@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} cat`;
}

@Put(':id')
https://docs.nestjs.com/controllers 15/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
@Put( :id )
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
return `This action updates a #${id} cat`;
}

@Delete(':id')
remove(@Param('id') id: string) {
return `This action removes a #${id} cat`;
}
}

HINT
Nest CLI offers a generator (schematic) that automatically creates all the boilerplate code, saving you from
doing this manually and improving the overall developer experience. Learn more about this feature here.

Getting up and running


Even with the CatsController fully defined, Nest doesn't yet know about it and won't automatically create an
instance of the class.

Controllers must always be part of a module, which is why we include the controllers array within the
@Module() decorator. Since we haven’t defined any other modules apart from the root AppModule , we’ll use it to
register the CatsController :

app.module.ts JS

import { Module } from '@nestjs/common'; content_copy


import { CatsController } from './cats/cats.controller';

@Module({
controllers: [CatsController],
})
export class AppModule {}

We attached the metadata to the module class using the @Module() decorator, and now Nest can easily determine
which controllers need to be mounted.

https://docs.nestjs.com/controllers 16/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

Library-specific approach
So far, we've covered the standard Nest way of manipulating responses. Another approach is to use a library-
specific response object. To inject a specific response object, we can use the @Res() decorator. To highlight the
differences, let’s rewrite the CatsController like this:

JS

import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common'; content_copy


import { Response } from 'express';

@Controller('cats')
export class CatsController {
@Post()
create(@Res() res: Response) {
res.status(HttpStatus.CREATED).send();
}

@Get()
findAll(@Res() res: Response) {
res.status(HttpStatus.OK).json([]);
}
}

While this approach works and offers more flexibility by giving full control over the response object (such as header
manipulation and access to library-specific features), it should be used with caution. Generally, this method is less
clear and comes with some downsides. The main disadvantage is that your code becomes platform-dependent, as
different underlying libraries may have different APIs for the response object. Additionally, it can make testing more
challenging, as you'll need to mock the response object, among other things.

Furthermore, by using this approach, you lose compatibility with Nest features that rely on standard response
handling, such as Interceptors and the @HttpCode() / @Header() decorators. To address this, you can enable the
passthrough option like this:

JS

@Get() content_copy
findAll(@Res({ passthrough: true }) res: Response) {
res status(HttpStatus OK);
https://docs.nestjs.com/controllers 17/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework
res.status(HttpStatus.OK);
return [];
}

With this approach, you can interact with the native response object (for example, setting cookies or headers based
on specific conditions), while still allowing the framework to handle the rest.

Support us

Nest is an MIT-licensed open source project. It can grow thanks to the support of these awesome people. If you'd
like to join them, please read more here.

Principal Sponsors Sponsors / Partners

Become a sponsor

Join our Newsletter


Subscribe to stay up to date with the latest Nest updates, features, and videos!

Email address..

Copyright © 2017-2025 MIT by Kamil Mysliwiec design by Jakub Staron


Official NestJS Consulting Trilon.io hosted by Netlify

https://docs.nestjs.com/controllers 18/19
23:18 6/7/25 Controllers | NestJS - A progressive Node.js framework

https://docs.nestjs.com/controllers 19/19

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy