前面介紹了 nestjs 三種基礎的元件, Module, Provider 與 Controller。可以處理簡單的後端 api 功能。
nestjs 對於 request flow 提供了更細部的分層元件,來讓整個 request flow 的職責可以切分的更細緻。讓開發者可以把不同關注點的邏輯做隔離。使得該元件只會修改只會與其職責相關,儘可能做到單一職責原則。
這篇會從 Middleware 開始介紹。
這邊的分層架構是以 http request 整個生命周期來做橫切。 request 從進入 nestjs 應用依序會從 Middleware , Guard , Interceptor , Pipe , Controller 傳入找到對應的 service 執行。執行結果,會從依序從 Controller, Interceptor , Exception Filter(如果有 Exception 的話) 傳出。
Middleware 是 http request 的處理最外一關,可以用添加資料到 request 或是 response。比如透過 request header cookie 的 session id 查出對應的 session 資料放入 execution context 讓後許的處理可以沿用資料。或是根據某些結果在 response header 做一些設置。另外,也可以用來做簡單的 log 功能,紀錄每次 request 資料的執行時間 ,與回應的 http code 。
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './middleware/logger.middleware';
@Module({
imports: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}
可以注意到 middleware 的影響範圍基本上可以設定哪些 route 被使用,另外也可以使用排除法,排除不需要的 route 。
在 main.ts 中,本身透過 nestjs Factory 產生出來的 app,本身屬於 INestApplication 。具有跟 expressjs 的 app 一樣功能,可以透過 app.use 來套用 Middleware 功能。 所以如果是一個全域的 Middleware,可以透過這種方式使用入如下:
onst app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
authentication.middleware.ts
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
import { RequestService } from '../request.service';
@Injectable()
export class AuthenticationMiddleware implements NestMiddleware {
private readonly logger = new Logger(AuthenticationMiddleware.name);
constructor(private readonly requestService: RequestService) {}
use(req: Request, res: Response, next: NextFunction) {
this.logger.log(AuthenticationMiddleware.name);
// Authenticate the request
const userId = '123';
this.requestService.setUserId(userId);
next();
}
}
app.module.ts
import { MiddlewareConsumer, NestModule } from '@nestjs/common';
import { AuthenticationMiddleware } from './middleware/authentication.middleware';
import { RequestService } from './request.service';
@Module({
providers: [
RequestService,
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(AuthenticationMiddleware).forRoutes('*');
}
}
nestjs 的 Middleware 元件提供一個可以把對 http request 與回應做處理的元件。最常用來實作身份驗證的 session 處理,或是做 log 稽核。妥善地利用這個元件有助於把共用邏輯做的良好隔離。