Controller Concept
Controllers in NestJS are classes responsible for handling incoming requests and returning responses. They use decorators to associate routes, HTTP methods, request bodies, etc., and are the entry points of the application.
Basic Controller Structure
typescriptimport { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() findAll() { return this.usersService.findAll(); } @Get(':id') findOne(@Param('id') id: string) { return this.usersService.findOne(id); } @Post() create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } @Put(':id') update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.usersService.update(id, updateUserDto); } @Delete(':id') remove(@Param('id') id: string) { return this.usersService.remove(id); } }
Route Decorators
@Controller()
The @Controller() decorator is used to define controller classes and can specify a route prefix:
typescript@Controller('users') export class UsersController {}
HTTP Method Decorators
NestJS provides decorators for all standard HTTP methods:
@Get()- GET request@Post()- POST request@Put()- PUT request@Patch()- PATCH request@Delete()- DELETE request@Options()- OPTIONS request@Head()- HEAD request@All()- All HTTP methods
typescript@Get() findAll() { return this.usersService.findAll(); } @Post() create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); }
Route Parameters
Path Parameters
Use the @Param() decorator to get path parameters:
typescript@Get(':id') findOne(@Param('id') id: string) { return this.usersService.findOne(id); } // Or use object destructuring @Get(':id') findOne(@Param() params: { id: string }) { return this.usersService.findOne(params.id); }
Query Parameters
Use the @Query() decorator to get query parameters:
typescript@Get() findAll(@Query('page') page: number, @Query('limit') limit: number) { return this.usersService.findAll(page, limit); } // Or get all query parameters @Get() findAll(@Query() query: { page: number; limit: number }) { return this.usersService.findAll(query.page, query.limit); }
Request Body
Use the @Body() decorator to get the request body:
typescript@Post() create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } // Or get specific fields @Post() create(@Body('name') name: string, @Body('email') email: string) { return this.usersService.create({ name, email }); }
Request Headers
Use the @Headers() decorator to get request headers:
typescript@Get() findAll(@Headers('authorization') authorization: string) { return this.usersService.findAll(authorization); } // Or get all headers @Get() findAll(@Headers() headers: Record<string, string>) { return this.usersService.findAll(headers); }
Request and Response Objects
Using @Req() and @Res()
typescriptimport { Req, Res } from '@nestjs/common'; import { Request, Response } from 'express'; @Get() findAll(@Req() req: Request, @Res() res: Response) { const data = this.usersService.findAll(); return res.json(data); }
Note: When using @Res(), you must explicitly call a response method (such as res.json()), otherwise the request will hang.
Status Code
Use the @HttpCode() decorator to set the status code:
typescript@Post() @HttpCode(201) create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); }
Response Headers
Use the @Header() decorator to set response headers:
typescript@Get() @Header('Cache-Control', 'no-cache') findAll() { return this.usersService.findAll(); }
Redirects
Use the @Redirect() decorator or redirect() method:
typescript@Get() @Redirect('https://nestjs.com', 301) findAll() { return this.usersService.findAll(); } // Or dynamic redirect @Get('docs') @Redirect() getDocs(@Query('version') version) { if (version && version === '5') { return { url: 'https://docs.nestjs.com/v5/', statusCode: 301 }; } }
Route Wildcards
NestJS supports route wildcard patterns:
typescript@Get('ab*cd') findAll() { // Matches abcd, abxcd, abRANDOMcd, ab123cd, etc. }
Subdomain Routing
Use the host option of the @Controller() decorator:
typescript@Controller({ host: 'admin.example.com' }) export class AdminController { @Get() index() { return 'Admin page'; } }
Controller Scope
Controllers use singleton mode by default, but can be configured with decorators:
typescriptimport { Scope } from '@nestjs/common'; @Controller({ path: 'users', scope: Scope.REQUEST }) export class UsersController {}
Best Practices
- Keep Controllers Simple: Controllers should only handle requests and responses, business logic should be in services
- Use DTO Validation: Use Data Transfer Objects (DTOs) to validate and transform request data
- Follow RESTful Conventions: Use correct HTTP methods and status codes
- Use Class Validators: Combine
class-validatorandclass-transformerfor data validation - Avoid Direct Express Object Usage: Prefer NestJS decorators over directly manipulating Request/Response objects
- Organize Routes Reasonably: Use meaningful route prefixes and parameter names
- Error Handling: Use exception filters to handle errors uniformly
Summary
The NestJS controller and routing system provides:
- Declarative route definitions
- Rich decorator support
- Flexible parameter retrieval methods
- Complete HTTP method support
- Clear code organization structure
Mastering controllers and routing is the foundation for building NestJS applications, enabling developers to quickly define API endpoints and handle various HTTP requests.