跳到主要内容

版本控制

提示

本章节仅适用于基于 HTTP 的应用程序。

版本控制允许您在同一个应用程序中运行不同版本的控制器或个别路由。 应用程序经常发生变化,而且通常会出现需要进行破坏性更改的情况, 而您仍然需要支持先前版本的应用程序。

支持四种版本控制的类型:

URI Versioning版本将在请求的 URI 中传递(默认)
Header Versioning自定义请求标头将指定版本
Media Type Versioning请求的 Accept 标头将指定版本
Custom Versioning请求的任何方面都可以用于指定版本。提供了一个自定义函数来提取所述版本。

URI 版本控制类型

URI 版本控制使用包含在请求 URI 中的版本, 例如 https://example.com/v1/routehttps://example.com/v2/route。

提示

使用 URI 版本控制时,版本将自动添加到 URI 中,位于全局路径前缀之后(如果存在的话), 并位于任何控制器或路由路径之前。

要启用应用程序的 URI 版本控制,请执行以下操作:

main.ts

const app = await NestFactory.create(AppModule);
// 或 "app.enableVersioning()"
app.enableVersioning({
type: VersioningType.URI,
});
await app.listen(3000);
提示

URI 中的版本默认会自动添加前缀 v,但是可以通过将 prefix 键设置为所需的前缀或 false(如果要禁用它)来配置前缀值。

提示

VersioningType 枚举可用于 type 属性,并从 @nestjs/common 包导入。

头部版本控制类型

头部版本控制使用自定义的、由用户指定的请求头来指

定版本,其中头的值将是用于请求的版本。

使用头部版本控制的示例 HTTP 请求:

要启用应用程序的头部版本控制,请执行以下操作:

main.ts
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.HEADER,
header: 'Custom-Header',
});
await app.listen(3000);

header 属性应该是包含请求版本的头的名称。

提示

VersioningType 枚举可用于 type 属性,并从 @nestjs/common 包导入。

媒体类型版本控制类型

媒体类型版本控制使用请求的 Accept 头来指定版本。

Accept 头中,版本将与媒体类型用分号 ; 分隔。 它应该包含一个键值对,表示用于请求的版本, 例如 Accept: application/json;v=2。当确定将配置哪个版本时,该键被视为前缀。

要启用应用程序的媒体类型版本控制,请执行以下操作:

main.ts
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.MEDIA_TYPE,
key: 'v=',
});
await app.listen(3000);

key 属性应该是包含版本的键值对的键和分隔符。 例如 Accept: application/json;v=2key 属性应设置为 v=

提示

VersioningType 枚举可用于 type 属性,并从 @nestjs/common 包导入。

自定义版本控制类型

自定义版本控制使用请求的任何方面来指定版本(或多个版本)。 传入请求会使用extractor函数进行分析,该函数返回一个字符串或字符串数组。

如果请求者提供了多个版本,则提取器函数可以返回一个字符串数组,按照最高版本到最低版本的顺序排序。 版本按照从高到低的顺序与路由匹配。

如果从extractor返回一个空字符串或数组,则不匹配任何路由,并返回 404。

例如,如果传入请求指定支持版本 123,则extractor必须返回 [3, 2, 1]。 这确保首先选择最高可能的路由版本。

如果提取到了版本 [3, 2, 1],但路由仅适用于版本 21,将选择匹配版本 2 的路由(版本 3 将自动被忽略)。

提示

根据从extractor返回的数组选择最高匹配版本 > 与 Express 适配器由于设计限制不可靠。 单个版本(字符串或包含 1 元素的数组)在 Express 中可以正常工作。 Fastify 正确支持最高匹配版本选择和单版本选择。

要启用应用程序的自定义版本控制,请创建extractor函数并将其传递到应用程序中,如下所示:

main.ts

// 例如,提取器函数从自定义头中提取版本列表并将其转换为排序的数组。
// 该示例使用 Fastify,但可以以类似的方式处理 Express 请求。
const extractor = (request: FastifyRequest): string | string[] =>
[request.headers['custom-versioning-field'] ?? '']
.flatMap(v => v.split(','))
.filter(v => !!v)
.sort()
.reverse()

const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.CUSTOM,
extractor,
});
await app.listen(3000);

用法

版本控制允许您对控制器、个别路由进行版本化,并为某些资源提供一种不使用版本控制的方式。 无论应用程序使用的是哪种版本控制类型,使用版本控制的方式都是相同的。

备注

如果为应用程序启用了版本控制,但控制器或路由没有指定版本,则对该控制器/路由的任何请求都将返回 404 响应状态。 同样,如果收到包含没有相应控制器或路由的版本的请求,也将返回 404 响应状态。

控制器版本

可以为控制器应用版本,为控制器内的所有路由设置版本。

要为控制器添加版本,请执行以下操作:

cats.controller.ts

@Controller({
version: '1',
})
export class CatsControllerV1 {
@Get('cats')
findAll(): string {
return 'This action returns all cats for version 1';
}
}

路由版本

可以为个别路由应用版本。此版本将覆盖影响路由的任何其他版本,如控制器版本。

要为个别路由添加版本,请执行以下操作:

cats.controller.ts

import { Controller, Get, Version } from '@nestjs/common';

@Controller()
export class CatsController {
@Version('1')
@Get('cats')
findAllV1(): string {
return 'This action returns all cats for version 1';
}

@Version('2')
@Get('cats')
findAllV2(): string {
return 'This action returns all cats for version 2';
}
}

多版本

可以为控制器或路由应用多个版本。要使用多个版本,可以将版本设置为一个数组。

要添加多个版本,请执行以下操作:

cats.controller.ts

@Controller({
version: ['1', '2'],
})
export class CatsController {
@Get('cats')
findAll(): string {
return 'This action returns all cats for version 1 or 2';
}
}

版本 "Neutral"

有些控制器或路由可能不关心版本,而且无论版本如何都将具有相同的功能。 为此,版本可以设置为 VERSION_NEUTRAL 符号。

无论请求中是否包含版本,都将映射到 VERSION_NEUTRAL 控制器或路由,除非请求中的 URI 不包含版本。

备注

对于 URI 版本控制,VERSION_NEUTRAL 资源在 URI 中不包含版本。

要添加版本中性的控制器或路由,请执行以下操作:

cats.controller.ts

import { Controller, Get, VERSION_NEUTRAL } from '@nestjs/common';

@Controller({
version: VERSION_NEUTRAL,
})
export class CatsController {
@Get('cats')
findAll(): string {
return 'This action returns all cats regardless of version';
}
}

全局默认版本

如果不想为每个控制器/或个别路由提供版本, 或者如果希望为没有指定版本的每个控制器/路由设置特定版本作为默认版本, 可以设置 defaultVersion 如下:

main.ts

app.enableVersioning({
// ...
defaultVersion: '1'
// 或
defaultVersion: ['1', '2']
// 或
defaultVersion: VERSION_NEUTRAL
});

中间件版本控制

中间件还可以使用版本控制元数据来为特定路由的版本配置中间件。 为此,请将版本号作为 MiddlewareConsumer.forRoutes() 方法的参数之一:

app.module.ts

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
import { CatsController } from './cats/cats.controller';

@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET, version: '2' });
}
}

在上述代码中,LoggerMiddleware 仅将应用于 /cats 端点的版本 '2'

备注

中间件适用于本节描述的任何版本控制类型:URIHeaderMedia TypeCustom