在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请求添加版本控制功能,确保旧版本客户端能够及时获得更新提示,从而提升用户体验。这种方法不仅适用于版本控制,也适用于其他需要在请求和响应之间进行处理的场景,比如日志记录、权限验证等。

美团外卖红包 饿了么红包 支付宝红包