乐闻世界logo
搜索文章和话题

How do NestJS controllers and routing work?

2月17日 22:32

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

typescript
import { 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()

typescript
import { 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:

typescript
import { Scope } from '@nestjs/common'; @Controller({ path: 'users', scope: Scope.REQUEST }) export class UsersController {}

Best Practices

  1. Keep Controllers Simple: Controllers should only handle requests and responses, business logic should be in services
  2. Use DTO Validation: Use Data Transfer Objects (DTOs) to validate and transform request data
  3. Follow RESTful Conventions: Use correct HTTP methods and status codes
  4. Use Class Validators: Combine class-validator and class-transformer for data validation
  5. Avoid Direct Express Object Usage: Prefer NestJS decorators over directly manipulating Request/Response objects
  6. Organize Routes Reasonably: Use meaningful route prefixes and parameter names
  7. 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.

标签:NestJS