创建 RESTful 服务,有 GET 和 POST 足矣?

  • Dilip Krishnan
  • 马国耀

2010 年 6 月 24 日

话题:SOAREST架构

Mike Amundsen在一篇博文中探讨了在仅限于使用 GET 和 POST 的环境中如何开发 RESTFul 的服务。

当我每次与人谈到 REST 架构风格时,人们给我的印象都是,除非使用PUTDELETE这两个 HTTP 方法,不然你的应用就不能算是 RESTful 的。这是不对的。

为了解释该问题,他转而回答了几个小问题,并通过它们证明,只要针对正确的操作使用了正确的 HTTP 方法,服务就是 RESTful 的。

操作是否安全?

他反复地说,代理通过检查 HTTP 方法来判断操作的安全性。只要通过 HTTP 方法表达的操作的目的与该操作的实现保持一致,操作就是安全的。

在实现中不要使用安全方法(如GETHEAD)进行不安全的操作(如,写数据),这点非常重要。[……] 因为 HTTP 将 GET 定义为“安全的”操作,所以缓存(Cache)和其他代理就会(基于 HTTP 规范)理所当然地认为对相应的 URI 执行“预取(pre-fetch)”、或根据需要缓存响应并重播这些响应(replay the responses)是没有问题的。

POST 不够吗?对于不安全的操作,我们是否需要 PUT 和 DELETE?

虽然在这个问题上,许多示例和文章都建议这么做(也就是使用 PUT 和 DELETE),但是他强调了 RESTful 的服务接口不应该总是 CRUD 接口。

[……] 另一普遍观念是仅仅使用POST去执行所有操作不算 RESTful。换言之,除非你使用了 PUT 和 / 或 DELETE,不然你就不能称你的实现是支持 REST 的。这个错误的假设往往是仅通过CRUD操作的透镜去看 REST 所得到的副产品,即 REST== HTTP 之上的 CRUD。还是那句话,虽然可以在 HTTP 之上实现 CRUD,但它不是 REST,只是 HTTP 之上的 CRUD。

他继续搬出了 Roy Fielding 的在博客中说的话,“用 POST 是没问题的。

我们没有必要对于每次 HTTP 中的状态修改都使用 PUT。REST 从来没有要求我们应该这么做。

但是,只有 GET 和 POST 真能做任何事情吗?

当然可以”,他说道,“很多年来一直是这么做的,并不需要什么神奇的玩意儿。不需要特别的 HTTP 头;不需要在 URI 中指定动作;不需要在消息体中设置方法参数”。接着,它给出了在某服务器上的操作队列的示例。

例如,暴露公共资源,客户端通过请求(Request)向服务端提交数据,请求被加入到一个列表中等待处理:

  POST /users/pending-updates/
  或 
  POST /users/pending-deletes/

该模型与Tim Bray在 Sun 的 VM API(Tim 称之为Slow REST)的设计中的用到的思想非常相似。该思想来源于 Craig McLanahan 的关于处理异步操作请求的建议书。

对于任何或所有的 PUT/POST/DELETE 操作,我们返回“202 进行中 (In progress)”和一个新的“状态(Status)”资源,该资源包含,一个 0 至 100 的进度标识 (progress);一个指定操作作用对象的 target_uri;一个指定操作的 op;以及当 progress 达到 100 时,指代应用程序返回结果的 status 和 message 域。其思想是提供一个钩子供实现者进行低廉的轮询。

Mike 在他的帖子中这样结尾,当 HTTP 方法的使用受到网络的限制,或者受到客户端的用户代理的限制而不能使用除标准的 GET 和 POST 之外的其他动词(如 PUT 和 DELETE)时,服务应该作出调整,并将客户引导到正确的表象、HTTP 方法和 URI。

由于 HTTP 将交互抽象成资源和通过URI寻址的表象,所以作出运行时的调整非但可以,而且协议在设计时就考虑了这点。通过这些层次的抽象以及在Fielding 的论文中描述的超媒体的限制(hypermedia constraint),你就能得到一个非常灵活的实现,不仅符合 HTTP 规范,而且能跨多种环境(甚至包括限用 GET 和 POST 的环境)支持 REST 架构风格的关键原则。

您的见解呢?请一定在此处或在原帖中发表出来。

查看英文原文Are GET And POST Enough To Create RESTful Services?

SOAREST架构