如何实现真正的REST风格?

SocialSite的REST API最近因Roy Fielding称其不符合REST风格而受到批评。Roy说,它是众多自称符合REST风格而实则不然的系统之一。

OpenSocial的REST API是RPC式的,而且是公然宣誓其RPC本性。它在如此多的方面存在耦合,所以理应将它评为“差”。

从OpenSocial网页上提供的信息来看,你不难同意Roy的观点。例如:

  • 在服务端为OpenSocial风格的REST和JSON-RPC提供支持
  • 在客户端为JSON-RPC批量请求提供支持
  • 服从OpenSocial对扩展的需求

另外,我们都知道REST跟RPC是紧密相关的。 鉴于已经见过很多自称符合REST风格而实则不然的网站,Roy接着就如何构建真正符合REST风格的网站(及API)给予了指导。现部分摘录如下:

  • REST API不应依赖于某一个通信协议。如果一个协议元素(protocol element)要将URI用于标识的目的,那么它必须允许采用任意URI方案(scheme)。[做不到这一点,就意味着标识与交互没有分离。]
  • 媒体类型(media types)是用于表示资源和推进应用状态(application state)的,REST API应将绝大部分描述精力用于定义媒体类型,或者是为现有的标准媒体类型定义扩展的关系名称(relation names)和/或基于超文本的标记(markup)。如果要就“对所谈及的URIs采用什么方法”进行定义的话,那么应完全把它放在媒体类型的处理规则 范围内进行定义(不过在大多数情况下,现有媒体类型都已经定义好了)。[做不到这一点,就意味着交互不是由超文本、而是由外部信息(out-of-band information)推进的。]
  • REST API一定不能定义固定的资源名称或层次。服务器必须可以自由控制它自己的名称空间(namespace)。应该像HTML表单(HTML forms)和URI模版(URI templates)那样,通过媒体类型和链接关系(link relations)给出指示,使得服务器可以指导客户端如何构造正确的URIs。[做不到这一点,就意味着客户端在根据外部信息(比如跟领域相关的标准)假定资源结构——相当于面向数据方法里的RPC功能耦合。]
  • 要使用REST API,应该只需知道初始URI(书签)和一套适合于目标用户(即可被任何使用该API的客户端所理解)的标准媒体类型。这样的话,所有的应用状态迁移, 都必须以“客户端在服务器提供的选项里挑选”这样的方式进行;服务器提供的选项,或者直接出现在用户收到的表示(representations)里,或 者在用户对那些表示进行处理后得到。客户端可以根据自己所掌握的关于媒体类型与资源通信机制的知识来决定(或限制)状态转移,客户端可以即时增加对媒体类 型与资源通信机制的支持(比如通过代码请求)。[做不到这一点,就意味着交互不是由超文本、而是由外部信息推进的。]

Roy的这篇文章收到了很多反馈,有的是直接回复评论,有的是另发文章,其中有人提出了一些关于超文本/超媒体使用的问题,对此Roy回答道:

我所说的 超文本(hypertext)指的是信息与控件的同时呈现,这样一来,信息便具有自解释性 (affordance)了,从而用户(或程序)可以通过它获取选项、并作出选择。超媒体(hypermedia)只是对文本的含义加以延伸、在媒体流里增 加了时间锚(temporal anchors);大部分研究者已经不对它们加以区分了。超文本不一定就是浏览器里的HTML。机器只要理解数据格式和关系类型,它就可以跟随链接。

当被问及为什么他觉得很多人未能正确实现REST风格时,Roy说:

某种程度上,人们未能正确实现REST风格,是因为我在博士论文里没有就媒体类型设计(media type design)作充分详细的论述。那并不是因为我觉得媒体 类型设计不如REST的其他方面重要,而是因为我当时时间不够。还有,我想很多人做得不对,可能是因为他们仅仅阅读了根据非权威资料撰写而成的 Wikipedia相关条目。不过,我觉得很多人存在一个错误的认识,他们认为:设计简单的东西,应该是轻而易举的。而在现实中,设计某样东西需要花费的 精力,与结果的简单 程度是成反比的。与其他架构风格相比,REST是相当简单的。REST是用于长远考虑的软件设计:它的每一个细节都是为了提升软件寿命和独立演化。有许多 约 束是直接与短期功效对立的。不幸的是,人们较擅长于短期设计,而对待长期设计就很糟糕了。大部分人认为他们不需要为以后的版本作考虑。有不少软件方法都把 长远 考虑说成是执迷不悟的、象牙塔的设计(若不是有实际需求的话,那么可能是的)。

实际上,如果你对REST感兴趣的话,对该文的所有回复都值得一读。Dare Obasanjo在一篇单独的文章中进行了概括总结:

最要铭记的是,REST所构建的,是在万维网(World Wide Web)上使用、对Web生态系统有利的软件。理想情况下,一个REST风格的API既可为众多网站所用、又可被运行在各种平台上的应用所用,而且客户 端应用与Web服务之间是零耦合的。RSS/Atom提要(feed)就是一个很好的例子,它也是世界上最成功的REST式API。

他专门考察了Roy提到了一种错误做法:实现API的服务需具有一种特定的URI结构。

这种做法的问题是,它假定每一个实现者都对他们的URI空间拥有完全控制权,而且客户端应该把URL结构写进代码里去。Joe Gregorio在文章 《No Fishing - or - Why 'robots.txt and 'favicon.ico' are bad ideas and shouldn't be emulated》里很好地解释了这一做法不好的原因,他在文章中列出了写死URL不好的几点理由,比如:缺乏扩展性;不支持那些采用寄存环境、从而无法控制URI空间的用户。

网上有大量其他REST资源(双关)。它们大部分由权威人士编写,并记录下了有关实现。不过显而易见的是,并不是所有使用Web的应用都是REST式应用,也并不是所有自称符合REST风格的应用都符合。

查看英文原文:What Makes Good REST?

你可能感兴趣的:(如何实现真正的REST风格?)