用過express
與koa
的同學,對中介軟體這個概念應該非常熟悉了,中介軟體可以拿到Request
、Response
物件和next
函數.
一般來講中介軟體有以下作用:
request-response
週期next()
呼叫下一個中介軟體request-response
週期,必須呼叫next()
函數,否則請求會處於掛起狀態,阻塞整個應用中介軟體一般有兩種:類中介軟體、函數中介軟體
使用@Injectable()
裝飾器,並且需要實現NestMiddleware
介面(use
方法)
// Logger.middleware.ts
import { Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response } from "express";
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}
}
類中間建立完之後,需要在模組中進行掛載,但@Module
裝飾器並沒有中介軟體的相關設定,我們需要讓module
類實現NestModule
介面,實現裡面configure方法來進行掛載
// user.module.ts
import { Module, NestModule } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware } from '../middleware/Logger.middleware';
@Module({
controllers: [UserController],
providers: [UserService]
})
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(UserController);
}
}
apply
方法表示掛載的是哪個中介軟體forRoutes
方法表示對哪個請求路徑起作用,這種方式與app.use(path, middleware)
作用是一樣,只針對部分路徑起作用forRoutes
方法傳遞的是一個controller
控制器時,那麼該中介軟體則對整個控制器下的路徑生效比如這裡傳遞的是UserController
控制器,那麼針對該控制器下的路徑都會生效
forRootes
方法還能做更詳細的設定,比如可以針對特定的請求方法、請求路徑可以使用正則匹配(需要注意的是使用fastify
驅動不能使用)export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
apply
可以同時掛載多箇中介軟體export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, aaaMiddleware, ...)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
forRoutes
可以使用單個string
路徑,多個string
路徑,RouteInfo
物件,單個Controller
,多個Controller
export class AppModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, NjMiddleware, ...)
.forRoutes(UserController, NjController, ...);
}
}
exclude
可以用來排除不使用中介軟體的路徑export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}
需要注意的是forRoutes
需要最後呼叫
這種方式較為簡單,使用起來與類中介軟體一致
export function LoggerMiddleware(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}
可以直接在入口檔案main.ts
中使用app.use
來掛載中介軟體,這樣掛載的中介軟體將全域性生效
app.use(LoggerMiddleware) // 紀錄檔中介軟體
中介軟體其實可以用來實現很多功能,比如:紀錄檔系統、cors跨域處理、圖片防盜等...
對圖片防盜感興趣的可以看我這篇文章:你不知道的 HTTP Referer
-------------------------------------------
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖 第一時間獲取最新的文章~
掃描下方二維條碼關注公眾號,回覆進群,拉你進前端學習交流群