在NestJS中實現基於請求頭的版本檢測——使用中間件實現

在上一篇文章《在NestJS中實現基於請求頭的版本檢測——使用攔截器實現》中,我們介紹了如何實現攔截器來實現對版本的檢測。

本文將以中間件為例,再來實現一遍該需求。

需求分析

需求很簡單:在每個請求的header中攜帶客戶端版本號,服務器根據這個版本號進行檢測。如果客戶端的版本低於服務器要求的最新版本,就需要在響應中附加一個更新提示字段;如果版本符合要求,則正常返回數據而不做修改。

如何實現

在NestJS中,我們可以通過中間件來捕獲請求並修改響應。在中間件中,我們可以:

  1. 獲取請求頭中的版本信息
  2. 判斷版本是否需要更新,通過簡單的版本號比較實現。
  3. 修改響應數據,如果需要更新,在返回數據中添加額外的字段。

1. 創建版本檢測中間件

中間件是NestJS中用於在請求生命週期中介入的工具。在這個場景下,我們需要創建一個中間件,負責在響應數據發回客戶端之前,對其進行版本檢測和處理。

1
import { Injectable, NestMiddleware } from "@nestjs/common";
2
import { Request, Response, NextFunction } from "express";
3
4
@Injectable()
5
export class VersionMiddleware implements NestMiddleware {
6
private readonly latestVersion = "2.0.0"; // 設定最新版本號
7
8
use(req: Request, res: Response, next: NextFunction) {
9
const version = req.headers["version"] as string; // 從header中獲取版本號
10
11
res.on("finish", () => {
12
if (version && this.needsUpdate(version)) {
13
// 如果需要更新,則修改響應數據
14
const originalSend = res.send;
15
res.send = (body: any) => {
16
let modifiedBody = body;
17
try {
18
modifiedBody = JSON.parse(body);
19
} catch (err) {}
20
21
const updateInfo = {
22
updateAvailable: true,
23
updateUrl: "xxxx", // 更新地址
24
latestVersion: this.latestVersion,
25
message: "A new version is available, please update.",
26
};
27
28
const updatedBody = { ...modifiedBody, ...updateInfo };
29
return originalSend.call(res, JSON.stringify(updatedBody));
30
};
31
}
32
});
33
34
next();
35
}
36
37
// 版本比較邏輯
38
private needsUpdate(clientVersion: string): boolean {
39
return clientVersion < this.latestVersion;
40
}
41
}

在這個中間件中,我們通過 req.headers['version'] 獲取客戶端傳來的版本號,並調用 needsUpdate 方法進行版本比較。如果客戶端版本較低,我們在響應發出之前修改數據,插入 updateAvailable 字段,告知用戶有新版本可用。

2. 應用中間件

在NestJS中,我們可以在應用程序的 main.ts 或者 app.module.ts 中註冊中間件。

app.module.ts 中註冊

1
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
2
import { AppController } from "./app.controller";
3
import { VersionMiddleware } from "./version.middleware";
4
5
@Module({
6
controllers: [AppController],
7
})
8
export class AppModule implements NestModule {
9
configure(consumer: MiddlewareConsumer) {
10
consumer.apply(VersionMiddleware).forRoutes("*"); // 對所有路由應用中間件
11
}
12
}

3. 測試接口

在完成中間件的設置後,我們可以通過 curl 或 Postman 來測試接口。客戶端通過請求頭發送版本信息,服務器將根據版本號返回相應的響應。

請求示例

Terminal window
1
curl -X GET http://localhost:3000/api/data -H "version: 1.0.0"

響應示例(需要更新時)

1
{
2
"data": "Here is your data",
3
"updateAvailable": true,
4
"latestVersion": "2.0.0",
5
"message": "A new version is available, please update."
6
}

響應示例(不需要更新時)

1
{
2
"data": "Here is your data"
3
}

總結

中間件是一種靈活且高效的方式,能夠在不修改業務邏輯的前提下處理版本檢測需求。通過這種方式,我們可以為所有的API請求添加版本控制功能,確保舊版本客戶端能夠及時獲得更新提示,從而提升用戶體驗。這種方法不僅適用於版本控制,也適用於其他需要在請求和響應之間進行處理的場景,比如日誌記錄、權限驗證等。