一、前言
在实际项目开发中,随着应用程序的迭代和用户需求的增加,原有的接口可能无法满足新的需求,或者需要进行较大的改动。这时,我们可以创建一个新的接口版本,而不是替换原来的接口。
这样,旧版本的客户端仍然可以使用原有的接口,而新版本的客户端则可以使用新的接口。
这种方式可以确保旧版本客户端的正常运行,同时也可以为新版本客户端提供更好的功能和性能。
此外,多版本接口也可以帮助我们在不影响现有功能的情况下添加新功能,这有助于降低开发和维护的成本。 多版本接口可以提高系统的可扩展性和灵活性,从而更好地满足用户的需求。
本文介绍下如何在NestJs中构建多版本接口?
二、具体实现
1、创建项目
首先,我们先创建一个NestJs项目:、
nest new versioned-interfaces
2、创建Version枚举类
进入项目目录,然后创建一个名为 Version 的枚举类,它将包含我们希望支持的所有接口版本号:
// src/common/enums/version.ts
export enum Version { V1 = 'v1', V2 = 'v2', V3 = 'v3'}
3、创建VersionGuard自定义Guard类
然后,我们将创建一个名为 VersionGuard 的自定义 Guard 类,用于验证接口版本。此 Guard 类将从请求头中读取接口版本号,并与我们支持的版本进行比较:
// src/common/guards/version.guard.ts
import { CanActivate, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
import { Observable } from 'rxjs';
import { versionRegex } from './version.utils';
export class VersionGuard implements CanActivate {
private versionRegex: RegExp;
constructor() {
this.versionRegex = versionRegex();
}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const version = request.headers.version;
if (!version) {
throw new HttpException('Missing version header', HttpStatus.BAD_REQUEST);
}
const match = version.match(this.versionRegex);
if (!match) {
throw new HttpException('Invalid version header format', HttpStatus.BAD_REQUEST);
}
const majorVersion = match[1];
const minorVersion = match[2];
if (parseInt(majorVersion) > Version.V2 || (majorVersion === Version.V2 && minorVersion > 1)) {
throw new HttpException(`Unsupported version: ${version}`, HttpStatus.FORBIDDEN);
}
return true;
}
}
在我们的版本守卫类中,我们使用正则表达式从请求头中提取出接口版本号,并与我们支持的版本进行比较。如果请求头中没有指定版本或指定了不支持的版本,则会抛出相应的错误。
4、创建VersionUtils辅助类
接下来,我们将创建一个名为 VersionUtils 的辅助类,用于验证和格式化接口版本号:
// src/common/utils/version.utils.ts
export function versionRegex(version: string): RegExp {
const [majorVersion, minorVersion = '0'] = version.split('.');
return new RegExp(`^v${majorVersion}.${minorVersion}$`);
}
export function toVersion(version: string): Version {
switch (version) {
case 'v1':
return Version.V1;
case 'v2':
return Version.V2;
default:
throw new Error(`Invalid version: ${version}`);
}
}
5、创建多版本接口
最后,我们将对控制器进行装饰,以应用版本守卫。以下是一个示例控制器:
// src/controllers/hello.controller.ts
import { Controller, Get, Header, HttpException, HttpStatus } from '@nestjs/common';
import { VersionGuard } from '../guards/version.guard';
@Controller()
export class HelloController {
constructor() {}
@Get()
@Header('version', '1') // 设置请求头,指定接口版本号为 v1
@UseGuards(VersionGuard)
helloV1() {
return 'Hello, version 1!';
}
@Get()
@Header('version', '2.1') // 设置请求头,指定接口版本号为 v2.1
@UseGuards(VersionGuard)
helloV2() {
return 'Hello, version 2.1!';
}
}
在上面的示例中,我们使用
@Header装饰器设置请求头中的接口版本号,并使用@UseGuards装饰器将版本守卫应用于相应的路由。
至此,我们已经完成了构建多版本接口的所有步骤。通过使用版本守卫和请求头,我们可以轻松地为不同的接口版本提供支持,并确保只有符合要求的请求才能通过验证并访问相应的路由。