REST APIs 必须是超文本驱动的

作者:Roy T. Fielding
原文:http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

(译注:作者是 HTTP 协议的作者之一,是 REST 相关理论的创始人)

长久以来,那么多人把任意基于 HTTP 的接口称为 REST API。对此,我每天都痛心泪流。目前的一个例子: SocialSite REST API(译注:本是一个连接,已失效)。这是一个 RPC(远程过程调用),它尖叫着说它自己是 RPC(而它的作者却说它是 REST API)。那么多的耦合,显得它差到极点!

在“超文本是一个约束”的基础之上,要弄清楚 REST 架构风格,需要做什么呢?换句话说,如果应用程序状态引擎(即API)不是由超文本驱动的,那么它就不是 RESTful 的,就不是一个 REST API。先前那些破手册是否要修正呢?

API的设计师啊,在把你的创作称为 REST API 之前,请对照以下规则:

  • 一个 REST API 不应依赖于任何一个通讯协议,然而,它可能因为出于对元数据的可用性(有效性)与方法的选择等方面的依赖,而需要一个特定协议的成功的映射。一般来说,使用 URI 作为标识的任何协议元素,为了标识的目的,必须允许使用不同的 URI 模式。「违背了这点,意味着标识与交互没有分离。」
    译注:这段如何理解?我认为这样的:REST API可以使用 HTTP 实现,也可以使用 FTP 实现。但由于考虑资源的可见性、缓存、接口的一致性、内容协商等架构元素,诚然,HTTP是最适合的,也几乎是专为 REST 而实现的一个协议。URI是资源的的标识符,它主要是指 host:port/path?query 这部分,这部分已经完整的标识了资源,它的模式是 http 还是 https 还是 ftp 都是无关要紧的,即前面所说的不依赖于通讯协议。)

  • REST API 不应该对通讯协议作任何修改,除非是对标准协议的特定字节的完善与修正。比如 HTTP 协议的 PATCH 方法与 Like 头字段。那些实现得不好的解决方法(如那些浏览器愚蠢到相信HTML定义了HTTP的方法集)应当单独或至少在附录中定义,并作最终被淘汰的思想准备。「违背这点,意味着那些资源接口为用于特定目的的,而不是用于一般目的的。」
    译注:这段的意思是,作为 REST API,不应擅自添加标准协议之外的东西,比如 Google 之前使用过一个 X-HTTP-Method-Override 的头字段来重写 POST 方法,这是不应该的。而 HTTP 的 PATCH,在 RFC 2616 上没有定义,但在 RFC 5789 中定义了,是对标准协议的完善,它本身就是一个标准,这是符合 RESTful 原则的。)

  • 一个 REST API 应该在它的描述上做出几乎所有的努力来定义媒体类型,用于呈现资源和驱动应用程序的状态;或者为已经存在的标准的媒体类型定义扩展的相关的名称,以及/或有超文本功能的标签。在描述感兴趣的 URL 上使用什么方法所做的努力,都应该完全在一个媒体类型的处理规则的范围之内定义(多数情况下已经被现有的媒体类型定义了)。「违背这点,意味着是其它信息驱动着交互,而不是超文本驱动交互。」
    译注:这段的理解比较费力。我想应该是这样的:应该选择已有的标准化的媒体类型来定义资源,比如 application/atom-xml,或者定义相关的扩展,如 application/vnd.example-xml。在这些类型上来定义方法,如 image/png 上使用 GET/PUT/DELETE 方法,而 application/x-www-form-urlencoded 可以 POST。我的理解可能是错的,仅当参考。)

  • 一个 REST API 不应该定义固定的资源名称和层次结构(客户端与服务器的一个明显的耦合)。服务器必须有控制他们自己的命名空间的自由。(与定义固定的资源名称和层次结构)相反,允许服务器通过在媒体类型与连接关系上定义指令,来指导客户端来如何构造合适的 URI,比如 HTML 表单和 URI 模板。「违背这点,意味着客户端需要通过额外的信息,比如专业领域的标准,来假定(猜测)资源的结构,这是等同于RPC功能的面向数据的耦合。」
    译注:曾记否?HTML 的 a 标签的 rel 属性,是用于表示连接关系的,服务器应该使用完整的连接,使用关系来让资源状态发生转变,实在无法确定连接的,应当使用明确的指令,如相对地址的规则,或 URL 模板,来帮助客户端构造 URI。绝对不能让客户端来猜测 URI。)

  • REST API 绝对不能使用类型化的资源给客户端来识别。在接口之后,定义规范的作者会使用一些资源类型来描述后台的实现,但这些资源对客户端来说是不适当的,不可见的。客户端能识别的唯一的资源类型是当前表征的媒体类型和标准化的扩展关系名。「同上」
    译注:即不能使用 Java 的类直接序列化给客户端,而是使用标准化的媒体类型,如 text/html)

  • 一个 REST API 应该通过使用初始的 URI (或收藏的连接)以及一组适合目标用户的标准化的媒体类型进入,而不需要先验知识(即让可能使用该API的任意客户端所理解)。这点上,所有状态转移必须由客户端上一次从服务器收到的表征所做的选择来驱动,或者暗示用户操作那些表征。这种转移可能由客户端对媒体类型和资源通讯机制的知识所决定或限制,两者都可能改善传输过程的状态转移(例如按需代码)。「违背这点,意味着是其它信息驱动着交互,而不是超文本驱动交互。」

可能还有一些规则我现在不记得了,但以上关于超文本的约束,是所谓的REST接口最经常侵犯的。如果你要设计 REST API,请时刻惦记这些约束!否则,就请另行另断,不要称为 REST API。

你可能感兴趣的:(REST)