【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
Web服务REST API版本控制是否有任何已知的方法或最佳实践?
我注意到AWS通过端点的URL进行版本控制 。 这是唯一的方法还是有其他方法来实现同一目标? 如果有多种方式,每种方式的优点是什么?
#1楼
将您的版本放在URI中。 API的一个版本并不总是支持另一个版本的类型,因此资源仅从一个版本迁移到另一个版本的论点是完全错误的。 这与将格式从XML切换到JSON不同。 这些类型可能不存在,或者它们可能在语义上发生了变化。
版本是资源地址的一部分。 您正在从一个API路由到另一个API。 在标题中隐藏寻址并不是RESTful。
#2楼
对REST API进行版本控制类似于任何其他API的版本控制。 可以进行微小的更改,主要更改可能需要一个全新的API。 最简单的方法是每次都从头开始,这就是将版本放入URL中最有意义。 如果您想让客户端更轻松,您可以尝试保持向后兼容性,可以使用弃用(永久重定向),多个版本的资源等。这更加繁琐,需要更多努力。 但它也是REST鼓励“酷URI不改变”的东西。
最后,它就像任何其他API设计一样。 权衡客户的便利性。 考虑为您的API采用语义版本控制,这使您的客户清楚地知道新版本的向后兼容性。
#3楼
这是一个很好而且棘手的问题。 URI设计的主题同时也是REST API中最突出的部分 ,因此可能是对该API用户的长期承诺 。
由于应用程序的演变以及在较小程度上它的API是生活中的事实,并且它甚至类似于看似复杂的产品(如编程语言)的演变,因此URI设计应该具有较少的自然约束并且应该保留一段时间 。 应用程序和API的生命周期越长,对应用程序和API用户的承诺就越大。
另一方面,生活中的另一个事实是很难预见通过API消耗的所有资源及其方面。 幸运的是,没有必要设计将在Apocalypse之前使用的整个API。 正确定义每个资源和资源实例的所有资源端点和寻址方案就足够了。
随着时间的推移,您可能需要为每个特定资源添加新资源和新属性,但是一旦资源寻址方案变为公共且因此最终,API用户访问特定资源所遵循的方法不应更改。
此方法适用于HTTP动词语义(例如,PUT应始终更新/替换)和早期API版本中支持的HTTP状态代码(它们应继续工作,以便在没有人为干预的情况下工作的API客户端应该能够继续工作像那样)。
此外,由于将API版本嵌入到URI中会破坏超媒体作为应用程序状态引擎的概念(在Roy T. Fieldings博士论文中阐述),因为资源地址/ URI会随着时间的推移而变化,我会得出结论API版本不应长时间保存在资源URI中,这意味着API用户可以依赖的资源URI应该是永久链接 。
当然, 可以在基URI中嵌入API版本,但仅限于合理和受限制的用途,例如调试与新API版本一起使用的API客户端 。 此类版本化API应该是有时间限制的,并且仅限于有限的API用户组(例如在封闭的测试版中)。 否则,你会把自己投入到你不应该做的地方。
有关维护API版本的一些想法,这些API版本具有到期日期。 通常用于实现Web服务(Java,.NET,PHP,Perl,Rails等)的所有编程平台/语言允许将Web服务端点轻松绑定到基URI。 通过这种方式,可以轻松收集并保持 不同API版本之间的文件/类/方法集合。
从API用户POV开始,当它显而易见但仅在有限的时间内(即在开发期间)时,它也更容易使用并绑定到特定的API版本。
从API维护者的POV中,通过使用主要处理文件的源控制系统作为(源代码)版本控制的最小单元,可以更容易地并行维护不同的API版本。
但是,在URI中清晰可见的API版本中有一个警告:人们也可能反对这种方法,因为API历史在URI设计中变得可见/明显 ,因此容易随着时间的推移而发生变化,这违反了REST的指导原则。 我同意!
解决这个合理异议的方法是在无版本API基URI下实现最新的API版本。 在这种情况下,API客户端开发人员可以选择:
针对最新版本进行开发(承诺维护应用程序,使其免受可能破坏其设计糟糕的API客户端的最终API更改)。
绑定到API的特定版本(变得明显),但仅限于有限的时间
例如,如果API v3.0是最新的API版本,则以下两个应该是别名(即行为与所有API请求相同):
http://shonzilla/api/customers/1234 http://shonzilla/api/v3.0/customers/1234 http://shonzilla/api/v3/customers/1234
此外, 如果他们使用的API版本已过时或不再受支持,则应通知仍尝试指向旧 API的API客户端使用最新的先前API版本。 因此,访问任何过时的URI,如下所示:
http://shonzilla/api/v2.2/customers/1234 http://shonzilla/api/v2.0/customers/1234 http://shonzilla/api/v2/customers/1234 http://shonzilla/api/v1.1/customers/1234 http://shonzilla/api/v1/customers/1234
应该返回任何指示重定向的30x HTTP状态代码,这些代码与Location
HTTP标头一起使用,重定向到仍然是这个的资源URI的适当版本:
http://shonzilla/api/customers/1234
至少有两个适用于API版本控制方案的重定向HTTP状态代码:
301永久移动,指示具有请求的URI的资源永久移动到另一个URI(应该是不包含API版本信息的资源实例永久链接)。 此状态代码可用于指示过时/不受支持的API版本,通知API客户端已将版本化资源URI替换为资源永久链接 。
302找到指示所请求的资源临时位于另一个位置,而仍可支持所请求的URI。 当无版本的URI暂时不可用并且应该使用重定向地址重复请求时(例如指向嵌入了APi版本的URI),此状态代码可能很有用,我们想告诉客户端继续使用它(即固定链接)。
其他方案可以在HTTP 1.1规范的重定向3xx章节中找到
#4楼
我们发现将版本放在URL中是实用且有用的。 它可以让您轻松了解您正在使用的内容。 我们使用别名/ foo到/ foo /(最新版本)以便于使用,更短/更清洁的URL等,正如接受的答案所暗示的那样。
永远保持向后兼容通常是成本过高和/或非常困难的。 我们更愿意提前通知弃用,重定向,如此处建议,文档和其他机制。
#5楼
URL不应包含版本。 该版本与您请求的资源的“想法”无关。 您应该尝试将URL视为您想要的概念的路径 - 而不是您希望项目返回的方式。 版本规定了对象的表示,而不是对象的概念。 正如其他海报所说,你应该在请求标题中指定格式(包括版本)。
如果查看具有版本的URL的完整HTTP请求,它看起来像这样:
(BAD WAY TO DO IT):
http://company.com/api/v3.0/customer/123
====>
GET v3.0/customer/123 HTTP/1.1
Accept: application/xml
<====
HTTP/1.1 200 OK
Content-Type: application/xml
<customer version="3.0">
<name>Neil Armstrong</name>
</customer>
标题包含包含您要求的表示的行(“Accept:application / xml”)。 那是版本应该去的地方。 每个人似乎都掩盖了这样一个事实,即你可能想要不同格式的相同的东西,并且客户应该能够询问它想要什么。 XML representation of the resource - not really the true representation of what it wants. 在上面的示例中,客户端要求资源的 XML表示 - 实际上并不是它想要的真实表示。 理论上,服务器可以返回与请求完全无关的内容,只要它是XML并且必须进行解析才能意识到它是错误的。
更好的方法是:
(GOOD WAY TO DO IT)
http://company.com/api/customer/123
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+xml
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+xml
<customer>
<name>Neil Armstrong</name>
</customer>
此外,假设客户认为XML太冗长,现在他们想要JSON。 在其他示例中,您必须为同一客户提供新的URL,因此您最终会得到:
(BAD)
http://company.com/api/JSONv3.0/customers/123
or
http://company.com/api/v3.0/customers/123?format="JSON"
(或类似的东西)。 实际上,每个HTTP请求都包含您要查找的格式:
(GOOD WAY TO DO IT)
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+json
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+json
{"customer":
{"name":"Neil Armstrong"}
}
使用这种方法,您可以更自由地设计,并且实际上遵循REST的原始概念。 您可以在不中断客户端的情况下更改版本,也可以在API更改时逐步更改客户端。 如果您选择停止支持表示,则可以使用HTTP状态代码或自定义代码响应请求。 客户端还可以验证响应的格式是否正确,并验证XML。
还有许多其他优点,我在我的博客上讨论了其中的一些优点: http : //thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
最后一个示例显示如何将版本放入URL中。 假设您想要在对象内部获得一些信息,并且您已经对各种对象进行了版本化(客户是v3.0,订单是v2.0,而shipto对象是v4.2)。 这是您必须在客户端中提供的令人讨厌的URL:
(Another reason why version in the URL sucks)
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3143699