Implementing Header-based Version Detection in NestJS — Using Middleware
- 575Words
- 3Minutes
- 14 Sep, 2024
In the previous article “Implementing Header-based Version Detection in NestJS — Using Interceptor”, we introduced how to implement version detection using interceptors.
In this article, we will implement the same requirement using middleware as an example.
Requirement Analysis
The requirement is simple: include the client version number in the header of each request, and the server checks this version. If the client’s version is lower than the required latest version, an update notification field should be added to the response; if the version is acceptable, return the data normally without modification.
How to Implement
In NestJS, we can capture requests and modify responses using middleware. In the middleware, we can:
- Retrieve version information from the request header.
- Check if the version needs to be updated by a simple version comparison.
- Modify response data. If an update is required, add an extra field to the returned data.
1. Creating the Version Detection Middleware
Middleware in NestJS is a tool that allows intervention in the request lifecycle. In this scenario, we need to create middleware responsible for version detection and handling the response data before it is sent back to the client.
1import { Injectable, NestMiddleware } from "@nestjs/common";2import { Request, Response, NextFunction } from "express";3
4@Injectable()5export class VersionMiddleware implements NestMiddleware {6 private readonly latestVersion = "2.0.0"; // Set the latest version7
8 use(req: Request, res: Response, next: NextFunction) {9 const version = req.headers["version"] as string; // Get version from header10
11 res.on("finish", () => {12 if (version && this.needsUpdate(version)) {13 // If an update is needed, modify the response data14 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", // Update URL24 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 // Version comparison logic38 private needsUpdate(clientVersion: string): boolean {39 return clientVersion < this.latestVersion;40 }41}
In this middleware, we get the client’s version via req.headers['version']
and call the needsUpdate
method to compare the version. If the client version is outdated, we modify the data before the response is sent, inserting the updateAvailable
field to inform the user that a new version is available.
2. Applying the Middleware
In NestJS, we can register middleware in the main.ts
or app.module.ts
file of the application.
Registering in app.module.ts
1import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";2import { AppController } from "./app.controller";3import { VersionMiddleware } from "./version.middleware";4
5@Module({6 controllers: [AppController],7})8export class AppModule implements NestModule {9 configure(consumer: MiddlewareConsumer) {10 consumer.apply(VersionMiddleware).forRoutes("*"); // Apply middleware to all routes11 }12}
3. Testing the API
After setting up the middleware, we can test the API via curl
or Postman. The client sends the version information via the request header, and the server responds accordingly based on the version.
Request Example
1curl -X GET http://localhost:3000/api/data -H "version: 1.0.0"
Response Example (When update is needed)
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}
Response Example (When no update is needed)
1{2 "data": "Here is your data"3}
Conclusion
Middleware provides a flexible and efficient way to handle version detection without modifying business logic. Through this method, we can add version control functionality to all API requests, ensuring that outdated client versions receive timely update notifications, improving user experience. This method can also be applied to other scenarios requiring processing between request and response, such as logging or authorization checks.