53

我查看了 API 版本控制的最佳实践?,但我不太相信答案,所以我用一个更具体的例子再次质疑版本控制部分。我有两个 URI(一个带有版本控制作为 URI 的一部分,一个没有):

http://xxxx/v1/user/123    -> favored solution in discussed thread
http://xxxx/user/123             

我怀疑第一个链接是否表达了 REST 的想法。我感到http://xxxx/v1/user/123困惑,因为它暗示有一天会有更高的 api 版本,比如http://xxxx/v2/user/123. 但这在 REST 术语中没有意义,api 版本本身是 HTTP 1.0 或 1.1,它已经在 HTTP 请求内部发送。这种以 REST 资源为中心的视图与 SOAP 或 Java 接口等其他 api 接口非常不同(在这些接口中,api 版本的限定名称很常见)。

在 REST 中,版本控制唯一有意义的是该资源的表示(例如,添加或删除新字段)。此版本控制属于内容协商的一部分,例如:

http://xxx/user/123 + HTTP 'Accept' Header -> Content negotation through header
http://xxx/user/123?v=1                    -> for perma-links/hyperlinks

也有人可能会争辩说,这种版本的内容协商可能是路径内 URI 的一部分,但我发现它违反直觉,因为您最终可能会为同一资源使用不同的 URI,并且必须在某些时候维护重定向。

总结一下:在 REST URI 中没有 api 版本控制,只有资源表示的版本控制。表示版本信息属于内容协商(如 queryParam 或 HTTP 'Accept')。

你怎么看?你会不同意/同意哪些事情?

4

8 回答 8

38

我完全同意; URI 表示身份,在引入新版本时身份不会改变。当然,可能会有用于其他概念的新 URI,并且现有 URI 可能会重定向……但在 URI 中包含“v2”对我来说是 RPCish。

请注意,这与 REST 无关,真的,因为从 REST 的角度来看,这一切都只是字符。

于 2010-01-08T15:27:15.163 回答
11

可以侦听X-API-VersionHTTP 请求标头。如果标头存在,则服务器必须使用该版本的 API。如果标头不存在,则服务器可能使用最新版本的 API。

> GET /user/123 HTTP/1.1
> Host: xxx
> X-API-Version: >=1.5.1, <2.0.0
> Accept: application/json
>

< HTTP/1.1 200 OK
< X-API-Version: 1.6.12
<
< { "user": { "id": 123, "name": "Bob Smith" } }
<
于 2010-01-08T15:42:36.497 回答
9

对于它的价值,我同意你的曼努埃尔。您可以在这个问题How to version REST URIs中看到我的推理

有很多人似乎不同意,但我不会担心。只要您尊重超文本约束,您的 url 看起来真的不会对您的客户产生太大影响。

于 2010-01-08T03:29:05.703 回答
2

我同意您不希望在 API 中提供的资源的 URI 中看到版本。这使他们不“酷”。也同意这是最有可能改变的陈述。

但是,它确实提出了当您更改特定表示的内容时会发生什么的问题。例如,如果您对 frobnitz 的原始 JSON 表示是

{"x": "bam", "y": "hello"}

并且您想添加一个“z”字段,您可能会觉得客户应该知道我们现在处于某种数据方案的第 2 版。

对此我不确定。我想你有几个选择:

  • 让您的客户灵活地面对一个轻轻变化的表示。在上面的示例中,我们仍在生成 JSON 字典。
  • 如果必须,请在表示本身中放置一个版本(本示例中的版本字段)。通过这样做,您实际上是在 JSON 内容类型中声明了一个子表示。我认为这是相当有限的。
  • 使用您自己的 MIME 类型和版本:application/x-my-special-json1.0、application/x-my-special-json1.1。这允许您彼此独立地对表示进行版本控制。同样,通过这个,您对您的客户提出了重要的要求,以了解正在发生的事情。

总的来说,我认为你想优化你的 API 和你自己没有发明的客户的表示;其他人会在发现您的资源后创建的内容。我相信即使在您制作私有内容的情况下这也是有用的,因为它构建了一个有用的设计约束,有助于使您的系统更加健壮。

于 2010-01-12T11:29:16.813 回答
1

我发现http://xxxx/v1/user/123 令人困惑,因为它表明有一天会有更高的 api-version 像http://xxxx/v2/user/123

这并不意味着-但是您将来具有这种能力。

但这在 REST 术语中没有意义,api 版本本身是 HTTP 1.0 或 1.1,它已经在 HTTP 请求内部发送。

您的 API 版本和用于发出请求的 HTTP 版本不必相同。

也有人可能会争辩说,这种版本的内容协商可能是路径内 URI 的一部分,但我发现它违反直觉,因为您最终可能会为同一资源使用不同的 URI,并且必须在某些时候维护重定向。

正如您所演示的,可以将版本作为 URI 参数。

http://xxx/user/123?v=1 -> 用于永久链接/超链接

于 2010-01-08T01:33:55.500 回答
1

另一种方法可能是说“一个表示具有多个 API”:

http://xxx/user/123/api/1.json

如果您愿意,您可以在这样的请求时使用最新的 API 返回表示:

http://xxx/user/123.json

就我个人而言,我更喜欢其他解决方案,但这是我在这里还没有看到建议的另一种方法。

于 2010-08-11T12:52:21.433 回答
0

对于 REST,大多数答案忘记的是数据元素。我假设多个版本的 API 仍然共享同一个数据层。这意味着数据层迫使您以向后兼容的方式思考。只有当您的 API 以向后兼容的方式更改时,才可能进行必须进行的重大更改。实际上,这意味着在您的 API 文档中使用 deprecation by date 来指示何时删除某些内容时,会以静默方式将其他属性添加到您的实体中。理想情况下,您使用带有 API 密钥用户电子邮件地址的注册方案,这样您就可以在一定范围内通知他们弃用(例如 Facebook)。因此,我认为您不需要在任何地方指定版本。

于 2014-07-16T17:53:47.207 回答
0

API 可以被视为顶级资源,/apis/v1/users/,那么在 URI 中包含版本号绝对没有错。对于 Semver,只有主要版本进入 URI,因为次要、补丁等是向后兼容的。

于 2021-06-07T08:42:58.883 回答