写点什么

如何实现真正的 REST 风格?

2008 年 10 月 28 日

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?

2008 年 10 月 28 日 02:432617
用户头像

发布了 63 篇内容, 共 22.4 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
  • 争论:REST 需要描述语言吗?

    追踪上周在此讨论的关于REST vs. WS-*的争论,值得注意的是,以REST化服务契约为主题的争论在最近几天日嚣尘上。

  • REST 的缺点是什么?

    REST架构师邮件列表中最近的一篇帖子引起了Ganesh Prasad的兴趣,促使他总结了自己看到的REST(基于HTTP)在更动态的点对点环境中的若干问题,并提出了解决办法。他建议从Web Services处学习经验。他还提到自己一直致力于提出的Internet Draft规约。

  • 新特性:Tomcat 如何支持 WebSocket?

    今天我会介绍WebSocket的工作原理,以及作为服务器端的Tomcat是如何支持WebSocket的。

    2019 年 6 月 20 日

  • Roy Fielding:REST API 必须是超文本驱动的!

    面对REST的泛滥,Roy Fielding博士终于按捺不住了。他指出“REST API必须是超文本驱动的!”

  • 可编程的互联网世界

    这一讲我们希望给大家呈现的是应用程序的全貌。当然,我们现在看到的仍然是非常高维的样子。

    2019 年 6 月 5 日

  • 你竟然不知道 SDP?它可是 WebRTC 的驱动核心!

    WebRTC之所以能很好地运转起来,完全是由SDP驱动的。

    2019 年 7 月 30 日

  • 如何通过 gRPC 实现高效远程过程调用?

    这一讲以一个实战案例,基于前两讲提到的HTTP/2和ProtoBuf协议,看gRPC如何将结构化消息编码为网络报文。

    2020 年 6 月 15 日

  • RESTful 世界里的 Cool URI

    假想一下,如果要以最小的集成代价实现一个分布在全世界范围的信息空间,用它来共享机器可识别的数据,会怎么样?这是关于REST的吗?不是的。根据 SWEO的说法,这跟语义网有关。那些Cool URI有助于实现这种方式。所以,去看看RESTful SOA URI是不是也很“酷”可能是值得的。

  • 持续演进,克服“REST 缺乏”

    新的API协议(如GraphQL、gRPC和Apache Kafka),作为受REST启发的HTTP API的替代品,越来越受到欢迎。

  • Restful Objects 简介

    Restful Objects是关于领域对象模型的超媒体API的公共规范。该规范的1.0.0 版本刚刚发布,并且目前已经出现了两个实现了该规范的开源框架——一个基于Java平台,另一个基于.NET平台。

  • 打住!SOA、SOA 2.0、ROA 和 WOA,缩略词也太过头了吧?

    当SOA 2.0风头已过,REST vs SOA vs Web服务的争论也不像之前那么激烈的时候,业界又有一些人开始宣扬面向Web的架构(WOA)。可这和现有的东西有任何区别吗(比如REST)?如果有的话,它是什么,它又是怎么样帮助开发者和部署者的呢?来自Burton Group的Anne Thomas Manes认为这一术语有些过头了,也并没有为现在的争论带来任何的价值。

  • 端到端的超媒体 REST API 设计

    Jimmy Bogard在他的一系列博客帖子中表示:REST是一种定义良好的架构风格,它能够为我们带来许多益处,但也经常被误用于描述各种各样的Web API。他特别着重描述了实现一个从服务器到客户端的端到端超媒体解决方案所必需的步骤,包括如何选择一种富超媒体的媒体类型。

  • GOTO Berlin: Web API 设计原则

    在邮件列表和讨论区中有很多有关于REST和Web API的讨论,而在GOTO Berlin大会上,InnoQ的首席顾问Oliver Wolf分享了他对这些讨论的一些见解,包括端点、领域模型、缓存、版本等内容。

  • 在 RESTful 服务中实现部分更新

    近期Alex Scordellis发表了一篇文章,文章主题是如何针对客户端与RESTFul服务的交互进行建模和设计,实现部分资源的更新。如果能够对资源进行恰当的建模,这个问题似乎可以很容易解决。很多时候考虑到把资源作为实体来支持CRUD操作也是这个问题,包括把建模的资源作为“资源”和提供的服务。

  • 应该如何理解请求方法?

    所谓的“请求方法”,它的实际含义就是客户端发出了一个“动作指令”,要求服务器端对URI定位的资源执行这个动作。

    2019 年 6 月 19 日

  • 11 丨性能脚本:用案例和图示帮你理解 HTTP 协议

    当前使用得最为广泛的应用层协议就是HTTP了。我想了好久,还是觉得应该把HTTP协议写一下。

    2020 年 1 月 8 日

  • 文章:描述 RESTful 应用程序

    如果服务器不将它自己的名字空间控制在一个固定的资源层次下,客户端及更重要的客户端开发者将如何知道或发现资源的URI呢?在这篇新文章中,Subbu Allamaraju对如何描述RESTful API进行了讨论,文章重点集中于超媒体而不是诸如WADL或WSDL 2.0这类带外(out-of-band)描述格式的使用上。<a href="http://www.infoq.com/cn/articles/subbu-allamaraju-rest" target="_blank">直接点击阅读完整文章</a>。

  • REST API 还有新麻烦?

    最近George Reese正在把他和Adrian Cole的一些使用REST和SOAP API开发云应用的经验写出来,在社区中引发了积极响应。刚开始只是些提示和建议,后来则演变成一场辩论,主题是抛开云的因素,使用REST来开发API是否存在真正的问题和误解。

  • MIME 给 REST 的采用带来了问题?

    在最近的一篇博文中,Benjamin Carlyle探讨了为什么他认为目前MIME的管理方式已成为深入采用REST的一个阻碍。他还提出了一些替代方法,但同时又指出这些方法也存在问题。

发现更多内容

秒杀活动要点分析

落朽

大数据 2 第十三周作业「架构师训练营第 1 期」

天天向善

架构师训练营第 1 期 - 第十三周总结

Todd-Lee

极客大学架构师训练营

架构师训练营 - 第十三周作业

一个节点

极客大学架构师训练营

架构师训练营第四周作业

zamkai

架构师训练营 week9 学习总结

花果山

极客大学架构师训练营

架构师训练营第九周作业2

韩儿

架构师训练营第13周作业

邓昀垚

架构师训练营 week9 课后作业

花果山

极客大学架构师训练营

架构师训练营 week10 学习笔记

花果山

极客大学架构师训练营

架構師訓練營 week13 總結

ilake

第九周课后练习

晴空万里

极客大学架构师训练营

架构师训练营第 9 周课后练习

菜青虫

极客大学架构师训练营

架构师训练营第十三周学习总结

Gosling

极客大学架构师训练营

分布式服务框架的选择-《企业IT架构转型之道-阿里巴巴中台战略思想与架构实战》

Man

分布式架构 中台架构

架构师训练营第 1 期 - 第十三周作业

Todd-Lee

极客大学架构师训练营

架构师训练营第一期第十三周总结

Leo乐

极客大学架构师训练营

第四周学习总结

简简单单

架构师训练营第十三周课后作业

Gosling

极客大学架构师训练营

海底光缆是如何铺设出来的?

第十三周作业

极客大学架构师训练营

架构师训练营 - 第十三周总结

一个节点

极客大学架构师训练营

盘点2020 | 带领团队学习成长,干货总结

架构精进之路

学习 盘点2020

架構師訓練營 week13 作業

ilake

架构师训练营第一期第十三周作业

Leo乐

极客大学架构师训练营

LeetCode题解:18. 四数之和,双指针,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

第四周系统架构作业

简简单单

架构师训练营第13周总结

邓昀垚

架构师训练营第九周作业1

韩儿

使用 Docker 部署 canal,并将消息推送到 RabbitMQ

AlwaysBeta

MySQL Docker RabbitMQ canal

架构师训练营第 9 周学习总结

菜青虫

极客大学架构师训练营

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

如何实现真正的REST风格?-InfoQ