[版本](https://github.com/kataras/iris/tree/master/versioning) 子程序包为你的 API 提供 [semver](https://semver.org/) 版本 。它实现了在 [api-指引](https://github.com/byrondover/api-guidelines/blob/master/Guidelines.md#versioning) 等处编写的所有建议。
版本比较是通过 [go-version](https://github.com/hashicorp/go-version) 包完成的。 它支持匹配诸如 `">= 1.0, < 3"` 等的模式。
```
import (
// [...]
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/versioning"
)
```
## [功能](https://github.com/kataras/iris/wiki/API-versioning#features)
- 对于每个路由版本匹配, 一个普通的 iris 处理程序, 带有 "switch" 案例通过版本 => 处理程序的映射。
- 每组版本化的路由和弃用API
- 版本匹配,例如 ">= 1.0, < 2.0" 或仅仅是 "2.0.1" 等。
- 找不到版本的处理程序 (可以通过简单地添加 versioning.NotFound 来自定义: customNotMatchVersionHandler 在映射上)
- 版本是从 "Accept" 和 "Accept-Version" 头中检索到的 (可以通过中间件进行自定义)
- 则以 "X-API-Version" 头响应 , 如果找到版本。
- 弃用的 "X-API-Warn", "X-API-Deprecation-Date", "X-API-Deprecation-Info" 头选项可以通过 `Deprecated` 封装。
## [获取版本](https://github.com/kataras/iris/wiki/API-versioning#get-version)
当前请求版本通过 `versioning.GetVersion(ctx)` 默认情况下,进行检索。
默认情况下, `GetVersion` 将尝试读取以下内容:
- `Accept` 头,即 `Accept: "application/json; version=1.0"`
- `Accept-Version` 头,即 `Accept-Version: "1.0"`
你还可以使用 Context 的存储值,通过中间件为处理程序设置自定义版本。例如:
```
func(ctx iris.Context) {
ctx.Values().Set(versioning.Key, ctx.URLParamDefault("version", "1.0"))
ctx.Next()
}
```
## [将版本与处理程序匹配](https://github.com/kataras/iris/wiki/API-versioning#match-version-to-handler)
`versioning.NewMatcher(versioning.Map) iris.Handler` 创建一个处理程序,该处理程序根据请求的版本决定需要执行哪个处理程序。
```
app := iris.New()
// 所有版本的中间件。
myMiddleware := func(ctx iris.Context) {
// [...]
ctx.Next()
}
myCustomNotVersionFound := func(ctx iris.Context) {
ctx.StatusCode(404)
ctx.Writef("%s version not found", versioning.GetVersion(ctx))
}
userAPI := app.Party("/api/user")
userAPI.Get("/", myMiddleware, versioning.NewMatcher(versioning.Map{
"1.0": sendHandler(v10Response),
">= 2, < 3": sendHandler(v2Response),
versioning.NotFound: myCustomNotVersionFound,
}))
```
### [弃用](https://github.com/kataras/iris/wiki/API-versioning#deprecation)
使用 `versioning.Deprecated(handler iris.Handler, options versioning.DeprecationOptions) iris.Handler` 函数,你可以将特定的处理程序版本标记为已弃用。
```
v10Handler := versioning.Deprecated(sendHandler(v10Response), versioning.DeprecationOptions{
//如果为空,则默认为: "警告! 你正在使用该API的不推荐使用的版本。"
WarnMessage string
DeprecationDate time.Time
DeprecationInfo string
})
userAPI.Get("/", versioning.NewMatcher(versioning.Map{
"1.0": v10Handler,
// [...]
}))
```
这将使处理程序将这些头发送到客户端:
- `"X-API-Warn": options.WarnMessage`
- `"X-API-Deprecation-Date": context.FormatTime(ctx, options.DeprecationDate))`
- `"X-API-Deprecation-Info": options.DeprecationInfo`
> versioning.DefaultDeprecationOptions 可以通过传递,如果你不在乎日期和信息。
## [按版本对路由进行分组](https://github.com/kataras/iris/wiki/API-versioning#grouping-routes-by-version)
也可以按版本对路由进行分组。
使用 `versioning.NewGroup(version string) *versioning.Group` 函数,你可以创建一个组来注册版本化路由。最后必须调用 `versioning.RegisterGroups(r iris.Party, versionNotFoundHandler iris.Handler, groups ...*versioning.Group)` 以便将路由注册到特定的`Party`。
```
app := iris.New()
userAPI := app.Party("/api/user")
// [... 静态服务,中间件等在这里].
userAPIV10 := versioning.NewGroup("1.0")
userAPIV10.Get("/", sendHandler(v10Response))
userAPIV2 := versioning.NewGroup(">= 2, < 3")
userAPIV2.Get("/", sendHandler(v2Response))
userAPIV2.Post("/", sendHandler(v2Response))
userAPIV2.Put("/other", sendHandler(v2Response))
versioning.RegisterGroups(userAPI, versioning.NotFoundHandler, userAPIV10, userAPIV2)
```
> 一个中间件仅仅能被注册到实际的`iris.Party` ,使用我们前面学到的方法。即通过使用 `versioning.Match` 来检测所需的代码/处理程序当请求 "x" 或没有版本时执行。
### [组弃用](https://github.com/kataras/iris/wiki/API-versioning#deprecation-for-group)
只需在要通知API使用者已弃用此特定版本的组上调用 `Deprecated(versioning.DeprecationOptions)` 。
```
userAPIV10 := versioning.NewGroup("1.0").Deprecated(versioning.DefaultDeprecationOptions)
```
## [从处理程序内部手动比较版本](https://github.com/kataras/iris/wiki/API-versioning#compare-version-manually-from-inside-your-handlers)
```
// 报告是否 "version" 和 "is" 匹配。
// "is" 可以是一个约束,例如 ">= 1, < 3"。
If(version string, is string) bool
```
```
// 与 `If` 相同,但希望上下文可以读取请求的版本。
Match(ctx iris.Context, expectedVersion string) bool
```
```
app.Get("/api/user", func(ctx iris.Context) {
if versioning.Match(ctx, ">= 2.2.3") {
// [处理程序的 >= 2.2.3 版本的逻辑在这里]
return
}
})
```