在 nestjs 框架中, Controller 是用來處理 client 的 HTTP 請求,並且給予回應邏輯的元件。
使用 @Controller 裝飾的類別,就是 Controller。而在 @Controller 中帶入的字串就是該 Controller 的 prefix 路徑。
以下是 blogController 的範例
import { Controller, Get, Post} from '@nestjs/common';
@Controller('blog')
export class BlogController {
@Get(':id')
GetArticle() {
// get article logic...
}
@Post()
@HttpCode(201)
CreateArticle() {
// create article logic...
}
}
在 nestjs 中,一些常見處理 request 的物件都可以在 @nestjs/common 找到,大致上都遵循著 expressjs 的規範, nestjs 預設的 http server 是 expressjs ,以下是 nestjs 與 expressjs 物件的對應表:
nestjs 物件 | expressjs 物件 |
---|---|
@Request(), @Req() | req |
@Response(), @Res() * | res |
@Next() | next |
@Session() | req.session |
@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 |
nestjs Controller 類別內每個路由處理函式的回傳值具有預設的格式,假設回傳值是 javascript 中的 primitive type 比如 string, number, boolean。則值結回傳不做序列化處理。而如果回傳值是 non-primitive type ,比如 javascript 的 object 或是 array ,則會自動地被 nestjs 序列化為 JSON 格式。
預設不指定的話,一般 handler 直接 return value 沒有 exception 之後的 http code 會是 200。而 POST 的成功預設 http code 回應值是 201。
如果想要自行定義成功回應 http code 可以使用 @HttpCode 裝飾子放在處理的 method 之前,如下
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
@Get()
async findAll(): Promise<Article[]> {
return new Array<Article>();
}
@Get()
findAll(): Observable<Article[]> {
return of(new Array<Article>());
}
nestjs 提供彈性,能夠使用 expressjs 的回應處理方法,如下:
import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common';
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([]);
}
}
但如果這樣做,就會無法讓 request 搭配原本 nestjs 內建 request lifecycle ,也就是使用相對應 event 處理邏輯,比如 Interceptor 等等來做回應處理。
想要使用 expressjs 回應方式,又想能夠搭配原本 nestjs 的 request lifecycle 就必須要在 @Res 物件搭入一個參數 passthrough: true ,舉例如下
@Get()
findAll(@Res({ passthrough: true }) res: Response) {
res.status(HttpStatus.OK);
return [];
}
這樣就可以在使用 expressjs 回應函數,且能套用原本 nestjs 的 request lifecycle 去處理。
nestjs 透過 Controller 元件來處理 http 的請求與回應,不論是在輸入解析與輸出回應的邏輯都會被包在這個元件之內。
後續更重要的處理 http 請求的整個 lifecycle 則會在之後的五個章節依序介紹。Module, Provider 與 Controller 是 nestjs 的基礎核心。透過這三個元件就能開發需多簡易的後端 api server 功能。
後續五個章節,將會介紹 nestjs 從分層架構的概念,延伸出更細緻的分工。讓整個開發職責能夠更區分明細,簡化處理流程。