x-ms-version 标头是旧版,仅为向后兼容而维护。事实上,自 2012 年引入 RFC 6648 以来,使用 x- 前缀的概念已被弃用。
在查询字符串中使用 api-version 是Microsoft REST API Guidelines 的§12 Versioning 中概述的官方约定之一。该指南还允许使用 URL 分段方法,但查询字符串方法是最多产的。
菲尔丁本人对 API 版本控制有非常强烈的看法 - 即不要这样做。实现版本化 REST API 的唯一普遍接受的方法是使用媒体类型协商。 (例如accept: application/json;v=1.0 或accept: application/vnd.acme.v1+json)。 GitHub 以这种方式对其 API 进行版本控制。
虽然媒体类型协商遵守 REST 约束并且实施起来并不难,但它是使用最少的方法。 为什么可能有很多解释,但实际上至少还有 3 种其他非常常见的方法:通过查询字符串、通过 URL 段或通过标题。
撇开迂腐的想法不谈,最常见的形式可能是因为客户可以轻松访问服务。标头方法与使用媒体类型协商没有太大区别。如果要使用标头,则使用带有媒体类型协商的accept 和content-type 标头是更好的选择。这给我们留下了查询字符串和 URL 段的方法。
虽然 URL 分段方法很常见,但它存在一些大多数服务作者没有考虑到的缺陷。它的扩散非常多,“嗯,[在此处插入公司]就是这样做的”。在我看来,URL 分段方法存在以下问题:
- URL 不稳定。它们会随着每个新的 API 版本而变化。
- 作为统一接口的一部分,URL path 应该用来标识资源。如果您的 URL 路径是
api/v1/products/123 和 api/v2/products/123,则意味着有两种不同的产品,这是不正确的。 v1 与 v2 URL 段意味着不同的表示。在所有 API 版本中,资源仍然是相同的逻辑产品。
- 如果您的 API 支持 HATEOAS,那么当您的资源版本控制不一致时,链接生成将是一个挑战。成熟的服务分类法和 REST 约束本身旨在帮助随着时间的推移发展服务和资源。期望
api/orders 可能是1.0 并且api/products/123 支持1.0-3.0 的引用行项目是完全可行的。如果版本号包含在 URL 中,那么服务应该生成什么 URL?它可以假定相同的版本,但这可能是错误的。任何其他选项都与相关资源耦合,可能不是客户想要的。服务无法知道客户端理解的不同资源的所有 API 版本。因此,服务器应该只生成普通资源标识符形式的链接(例如:api/products/123),并让客户端指定要使用的 API 版本。客户端对链接的任何其他操作都会大大降低支持 HATEOAS 的价值。当然,如果一切都是相同的版本或在相同的资源上,这可能不是问题。
- 2 和 3 可能会因保留资源链接的客户端而变得更加复杂。当 API 版本停用时,到该资源的所有旧链接现在都将被破坏,即使该资源仍然存在,尽管不是使用预期的但已过时的表示。
这使查询字符串方法更完整。虽然查询字符串确实会因 API 版本而异,但它是一个参数,而不是标识符的一部分(例如路径)。 URL 路径对所有版本的客户端保持一致。客户端也很容易为他们理解的版本附加查询参数。 API 版本通常也是数字的、基于日期的或两者兼而有之。有时他们也有地位。 URL api/products/123?api-version=2018-03-10-beta1 可以说比api/2018-03-10-beta1/products/123 更干净。
总之,虽然查询字符串方法可能不是真正的 RESTful 方法来对资源进行版本控制,但它倾向于携带更多预期的特征,同时保持易于使用(这不是 REST 约束)。与Microsoft REST API Guidelines 一起使用,这就是为什么ASP.NET API Versioning 默认使用开箱即用的查询字符串方法,即使所有这些方法都受支持。
希望这能提供一些有用的见解,说明除了纯粹的偏好之外,不同的风格如何影响您的服务分类。