现在的位置: 首页 > 综合 > 正文

HTTP API可演进性最佳实践

2019年06月18日 ⁄ 综合 ⁄ 共 2048字 ⁄ 字号 评论关闭

正如标题所示,Benjamin Carlyle试图在《Best Practices For HTTP API Evolvability》一文中为围绕HTTP API构建的系统的设计定义原则和实践,这些系统是可扩展的,并且能一直进化下去。他先指出了REST(一种架构风格)和HTTP API(通过HTTP暴露的编程接口)之间的区别。

HTTP API是针对一个特定服务的面向开发者的接口,也被称为RESTful服务契约面向资源架构URI
Space

我说REST和HTTP API紧密相关是因为大多数HTTP API并不严格遵守统一接口约束,严格说来统一接口约束要求接口是“标准的”[…]

文章开头他标识出了API设计中的不同元素,这些元素决定了API后续的进化。通常来说,API进化涉及到了设计客户端与服务器的兼容性;特别是API的向后和向前兼容变更。 变更频率按增序排列依次是:

  1. API中用到的方法的通用语义,包含异常条件和其他元数据
  2. API中用到的媒体类型的通用语义,包含全部Schema信息
  3. 构成API的URI集合,包含API中用到的每个通用方法和媒体类型的特定语义

API进化中改变最少的就是方法的语义。文中描述的最佳实践是识别出向前和向后兼容的变化,运用Postel法则让服务与客户端以一种更能容忍的方式进行进化。他建议尽可能地使用HTTP错误码来传达兼容性问题。

最佳实践3:新方法名应该选择那些不会和任何已有方法发生向前兼容的名字。例如,如果要处理的方法必须正确理解(必须理解语义)方法的新特性,那么应该选择一个新的方法名。

最佳实践4:服务应该忽略它们不理解的标头或组件。代理应该不加修改地传递这些标头,或者是无法理解的组件。

[…]

最佳实践7:在某个数字范围内为新状态分配一个状态码,这个范围可以粗粒度地标识已存在的条件。

[…]

最佳实践9:如果新状态是一个已知状态(除了400 Bad Request或500 Internal Server Error)的子集,可以向响应头添加信息来细化已知状态的含义,而不是分配一个新的状态码。

他指出了一个重要的区别,即客户端与服务器交互中媒体类型的对称本质。

[…]与客户端和服务器之间非对称的方法和状态不同,媒体类型通常能用作请求或响应的负载,即适用于两个方向。为此本节中我们不讨论客户端与服务器,而是讲发送端与接收端。

...这构成了与媒体类型相关的最佳实践的基础

[…]

最佳实践11:只有当验证逻辑是为与文档发送方相同版本或后续版本的API编写的情况下,才可能出现不符合最佳实践10的文档验证。

最佳实践12:在不违反媒体类型设计目标的前提下,如果能向现有媒体类型的Schema中添加新信息,那么就添加吧。

他提倡使用Content-Types和Accept标头来管理发送端与接收端之间的兼容性。

HTTP API习惯于做出向后不兼容的媒体类型Schema变更。新客户端请求或者提供了Schema中带有向后不兼容变更的新媒体类型。老的客户端继续请求或提供旧的媒体类型。直到所有重要的相关实现都升级到最新的媒体类型集之前,客户端与服务器端都应该要支持旧的媒体类型。

他认为对资源的修改,尤其是URI的修改都是服务器应该关心的事;如果客户端是设计成由超媒体约束驱动的话,一般这些修改都不应该引入兼容性问题。他提倡使用Cookies将客户端请求路由到合适的服务实例/服务器。

在使用多种通用方法时,我们不再处理通用的方法或媒体类型,而是和带有特定语义的特定URL打交道。[…]在考虑如下服务契约时,我倾向于采用以服务器为中心的视角:

  • GET /invoice/{invoice-id},返回媒体类型application/invoice+xml,内容是invoice-id指定的发货单
  • GET /invoice/{invoice-id}/paid,返回媒体类型text/plain(xsd:bool语法),内容是invoice-id指定的发货单的支付状态
  • PUT /invoice/{invoice-id}/paid,接受媒体类型text/plain(xsd:bool语法),设置invoice-id指定的发货单的支付状态

此外,他还提出了一些客户端的最佳实践,以便客户端能应对服务器URI的转变(transition)和进化。

最佳实践19:在升级时,服务应该通过Cookies追踪哪些客户端应该连接到旧的服务器,哪些应该连接到新的服务器,或者也可以使用类似的机制。

最佳实践20:即使不是在响应HEAD或GET请求,客户端也应该遵从服务器发回的重定向状态响应[说明:RFC2616]

最佳实践21:重新设计URL时,确保新的URL拥有和旧URL一样的语义,并将旧URL重定向到新的URL上。

本文中提供了一些基本原理,让HTTP API系统能随着时间不断进化。请务必阅读Benjamin Carlyle的完整原文以便对这一主题能有更深入的理解。

查看英文原文:Best Practices For HTTP API Evolvability

抱歉!评论已关闭.