2010-01-07 76 views
48

我看过Best practices for API versioning?,但我不太相信答案,所以我再次以更具体的示例质疑版本控制部分。我有两个URI(一个版本作为URI的一部分,一个没有):REST API版本化(仅版本表示,而不是资源本身)

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资源为中心的视图与其他api接口(如SOAP或Java接口(通常在限定名称中使用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'接受')。

您认为如何?你会不同意/同意哪些事情?

+1

只需添加一件小事。对我来说,使用v1和style的唯一好处就是,当你没有控制负载平衡,并且无法在前端机器上以HTTP头为基础定义到应用程序服务器的方向( - >内容协商是HTTP头的一部分)。通常标准是使用URL路径。在Web框架中,我可以想到,很难在基于HTTP头的控制器中定义请求映射端点而不是路径。 – 2010-01-21 05:16:49

回答

35

我完全同意;一个URI表示身份,在引入新版本时身份不会改变。当然,可能有新的URI用于附加概念,现有的URI可能会重定向,但在URI中包含一个“v2”会给我带来RPCish的味道。

请注意,这与REST无关,实际上,从REST的角度来看,这些都只是字符。

+2

是的,它只是字符。但拥有友好/一致的URI是很好的,因为它们是api用户程序所针对的接口的一部分。 – 2010-01-21 05:18:17

+1

这里是另一个很好的例子,说明如何不在你的url中使用版本控制,http://blog.steveklabnik.com/2011/07/03/nobody-understands-rest-or-http.html – kidbrax 2011-07-27 03:50:34

+1

这已经在在此之前更详细的http://stackoverflow.com/q/389169/104261。 – 2012-05-04 00:36:28

1

我发现http://xxxx/v1/user/123 混乱,因为它表明,有 将以更高的API版本哪天 像http://xxxx/v2/user/123

这并不意味着 - 然而你在未来的能力。

但是,这并不使REST 而言意义上讲,API版本本身就是HTTP 1.0或1.1,这已经是HTTP请求发送里面。

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

人们也可以说这样的版本 内容协商可能是 部分路内的URI,但我觉得它 反直觉的,因为你可以 结束了对 不同的URI相同的资源,并且必须在某个时刻保持 重定向。

可以将版本作为URI参数进行展示。

http://xxx/user/123?v=1 - >为博链接/链接

+0

感谢提示。但有一个问题:说出REST术语,你认为什么使得'YOUR API'的版本?因为除了HTTP协议和资源表示之外,我只是看不到REST应用程序内的版本。 – 2010-01-08 02:51:43

+4

我通常在v1上启动REST API。 api版本基本上是客户可以达成一致的合同/界面。如果我更改了interface/api,并且可能会中断该合同,那么我可能会增加到v2或v1.1 - 但是,我的版本推理没有反映发出请求的HTTP客户端的版本。这有帮助吗? – 2010-01-08 20:20:48

9

对于什么是值得的,我同意你的曼努埃尔。你可以看到我在这个问题的推理How to version REST URIs

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

+2

+1“只要您尊重超文本约束,”您的网址看起来真的不会对您的客户造成太大影响“。这不能够强调。 – 2011-07-05 08:08:27

+0

+1“只要你尊重超文本约束,你的网址看起来真的对你的客户端没有太大的影响” – andy 2014-03-25 02:58:34

10

您可以可以监听X-API-Version HTTP请求标头。如果标题存在,那么服务器必须使用该版本的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" } } 
< 
+0

但是,这难道不会因为各种中介(代理人,缓存)可能会或可能不会尊重这个标题而可能甚至不能通过它的风险而受到影响吗? – verveguy 2010-08-27 17:38:52

+0

可能 - 它肯定取决于代理。 – yfeldblum 2010-08-27 18:11:44

+0

太糟糕了,在某些情况下会删除标题。 – neoneye 2011-09-12 13:49:42

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和你的代表你没有发明自己的客户;其他人会在发现您的资源时创建的。我相信这是有用的,即使在您制作私有内容的情况下也是如此,因为它构建在有用的设计约束中,这将有助于使您的系统更加健壮。

1

另一种方法可以说,“一只表示有多个API”:

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

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

http://xxx/user/123.json 

就我个人而言,我更喜欢其他解决方案,但这是另一种我在此尚未见过的方法。

0

对于REST,大多数答案忘记的是数据元素。我假设多个版本的API仍然共享相同的数据层。这意味着数据层迫使您以向后兼容的方式思考。只有当您的API以向后兼容的方式进行更改时,才能做出必须完成的重大更改。实际上,这意味着附加属性会悄悄地添加到您的实体中,同时在您的API文档中使用按日期弃用来指示什么时候会被删除。理想情况下,您使用带有API密钥用户电子邮件地址的注册方案,以便您可以在特定范围内(Facebook账户)通知他们弃用。因此,我认为您不需要在任何地方指定版本。