API Discoverability¶
本文档旨在提供指导,说明如何让公共 REST API 以机器可读的方式向最终用户公开 URI 和资源。
另请参阅关于 使用服务目录 的主题文档。
另请参阅关于 版本发现 的主题文档。
版本化和非版本化端点¶
每个服务都应具有一个基本端点,该端点被称为服务的“非版本化”端点。
注意
强烈建议云运营商在 Keystone 目录中注册服务的非版本化端点。如果他们这样做,在 版本发现算法 中描述的过程将能够为 API 消费者提供最具功能性,并且效率最高。
每个服务必须至少有一个主要 API 版本。
如果服务具有或预计具有多个主要 API 版本,则每个版本都应具有一个基本端点,该端点被称为该服务版本的“版本化”端点。
所有版本发现文档必须可通过未认证的连接访问。
如果服务仅使用微版本并且仅有一个主要 API 版本,则该服务不应具有任何额外的“版本化”端点。
例如,在云 example.com 上的 Glance 服务可能有一个非版本化端点
https://image.example.com
然后,Glance 服务可能还提供三个主要版本,v1、v2 和 v3
https://image.example.com/v1
https://image.example.com/v2
https://image.example.com/v3
此外,在云 example.com 上的 Placement 服务可能有一个非版本化端点
https://placement.example.com
Placement 服务仅使用微版本,因此没有额外的版本化端点。
在两种情况下,非版本化端点都是建议在服务目录中注册的端点。
优先使用子路径¶
历史上,每个 OpenStack 服务都被赋予了一个端口。强烈建议不要使用这些端口,而是使用正常的 443 端口进行 https。如果要在单个机器上安装多个 API 服务,强烈建议使用子路径
https://api.example.com/compute
https://api.example.com/image
提出此建议的原因是方便用户使用,这些用户在其操作系统环境中可能具有限制端口阻止的防火墙。由于流量是 HTTP 流量而不是不同的协议,因此无需通过端口号来区分它,并且这样做会增加用户连接到各个 API 端点的问题的可能性。
版本发现¶
每个服务都应在服务的非版本化端点和每个版本化端点上提供一个版本发现 API,供客户端用于发现支持的 API 版本。
非版本化发现¶
每个服务应在其非版本化端点提供一个版本发现 API。它应向所有用户公开,无需身份验证。
注意
建议不要使用身份验证要求来保护版本发现 API。返回的信息不是特定于用户的,而是服务运行的基本 API 的基本特征。此外,v2 和 v3 身份验证 API 是不同的,因此在版本发现之前需要身份验证会使确定应使用 v2 或 v3 身份验证变得更加困难。
每个服务的非版本化版本发现 API 应返回一个版本信息列表,其中包含该服务提供的所有基本端点,以及该版本的最小和最大微版本。客户端使用这些值来发现支持的 API 版本。
{
"$schema": "https://schema.json.js.cn/draft-04/schema#",
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/version-information-schema.json#",
"type": "object",
"additionalProperties":false,
"required":[
"status",
"id",
"links"
],
"properties": {
"status": {
"description": "Support and lifecycle status of the versioned endpoint.",
"type": "string",
"enum": [
"CURRENT",
"SUPPORTED",
"EXPERIMENTAL",
"DEPRECATED"
]
},
"id": {
"description": "The major API version.",
"type": "string",
"pattern": "^v[0-9]{1,2}.?[0-9]{0,2}$"
},
"links": {
"$ref": "https://schema.json.js.cn/draft-04/links#"
},
"max_version": {
"desciption": "The maximum microversion available",
"type": "string",
"pattern": "^[0-9]{1,2}.[0-9]{1,2}$"
},
"min_version": {
"desciption": "The minimum microversion available",
"type": "string",
"pattern": "^[0-9]{1,2}.[0-9]{1,2}$"
}
}
}
{
"$schema": "https://schema.json.js.cn/draft-04/schema#",
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/unversioned-discovery-schema.json#",
"type": "object",
"required": ["versions"],
"additionalProperties": false,
"properties": {
"versions": {
"type": "array",
"items": {
"$ref": "version-information-schema.json#"
}
}
}
}
非版本化版本发现响应如下所示
GET /
{
"versions": [
{
"id": "v2.1",
"links": [
{
"href": "https://compute.example.com/v2/",
"rel": "self"
},
{
"href": "https://compute.example.com/",
"rel": "collection"
}
],
"status": "CURRENT",
"max_version": "5.2",
"min_version": "2.1"
},
]
}
列表中每个版本信息应包含以下信息
- id
主要 API 版本。遵循 版本控制 中概述的格式,前面加上“v”。必需。
- links
包含有关查找实际版本化端点的信息。请参阅 版本链接 下文。必需。
- status
版本化端点的支持和生命周期状态。必需。请参阅 端点状态
- max_version
如果服务的版本支持微版本,则可用的最大微版本。可选。请参阅 微版本规范
- min_version
如果服务的版本支持微版本,则可用的最小微版本。可选。请参阅 微版本规范
如果服务没有版本化端点,则应在文档中列出其基本端点,如下所示
GET /
{
"versions": [
{
"id": "v1.0",
"links": [
{
"href": "https://placement.example.com/",
"rel": "self"
},
{
"href": "https://placement.example.com/",
"rel": "collection"
}
],
"status": "CURRENT",
"max_version": "1.25",
"min_version": "1.0"
}
]
}
版本化发现¶
每个服务应在其每个版本化端点提供一个版本发现 API。它应向所有用户公开,无需身份验证。
版本化端点版本发现 API 返回的文档应与非版本化端点返回的文档相同。这样,正在寻找 API 版本客户端始终可以在一个步骤中获取完整信息,而不是一系列尝试、失败和重试。
然而,为了在不完美的过去中走向完美的未来,已经在其版本化端点上提供不同文档的服务,担心更改其版本化版本发现文档的有效负载从名为 version 的单个对象更改为名为 versions 的对象列表,尽管添加指向非版本化发现端点的链接仍然是一个进步。
对于不将版本化版本发现文档放在名为 version 的对象内,而是在根对象中直接包含信息的服务,同样建议添加 collection 链接。(有关定义的关联类型列表,请参阅 https://www.iana.org/assignments/link-relations/link-relations.xhtml)
{
"$schema": "https://schema.json.js.cn/draft-04/schema#",
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/versioned-discovery-schema.json#",
"type": "object",
"required": ["version"],
"additionalProperties": false,
"properties": {
"version": {
"$ref": "version-information-schema.json#"
}
}
}
例如
GET /v2
{
"version": {
"id": "v2.0",
"links": [
{
"href": "https://image.example.com/v2",
"rel": "self"
},
{
"href": "https://image.example.com/",
"rel": "collection"
}
],
"status": "CURRENT"
}
}
端点状态¶
通常,对于给定的服务,只有一个版本化的 API,但有时能够提供多个 API 版本也很有用。这方面的常见示例是,为了支持尚未升级到当前版本的客户端,仍然提供旧版本,或者在新 API 版本发布之前对其进行测试。为了区分相同服务的这些不同的 API,使用 status 值。可以返回以下值作为状态
- CURRENT
当前正在开发和改进的最新 API。除非您需要支持旧代码,否则请使用此 API。只有一个 API 必须标记为 CURRENT。
- SUPPORTED
API 的旧版本。不会向此版本添加新功能,但可能会修复代码中发现的任何错误。
- DEPRECATED
此 API 将在可预见的未来被删除。您应该开始计划使用替代方案。
- EXPERIMENTAL
此 API 正在开发中(“alpha”),您预计它会发生变化甚至被删除。
版本链接¶
注意
links 符合 链接 指南。
端点描述的 links 字段应至少包含两个条目,如下所示,按其 rel 字段的值列出。
- self
给定版本服务的基本端点的位置。
- collection
非版本化版本发现端点的基本端点的位置。
collection条目提供指导,允许客户端从在服务目录中列出的版本化端点导航到非版本化端点,如果他们正在寻找不同的版本,而无需诉诸猜测 URL 方案和执行 URL 操作。
指导¶
TODO 添加描述 API 可发现最佳实践的部分,可能使用 JSON-Home、JSONSchema 文档和 JSON-HAL。