Mike Amundsen在一篇博文中探讨了在仅限于使用 GET 和 POST 的环境中如何开发 RESTFul 的服务。
当我每次与人谈到 REST 架构风格时,人们给我的印象都是,除非使用 PUT 和 DELETE 这两个 HTTP 方法,不然你的应用就不能算是 RESTful 的。这是不对的。
为了解释该问题,他转而回答了几个小问题,并通过它们证明,只要针对正确的操作使用了正确的 HTTP 方法,服务就是 RESTful 的。
操作是否安全?
他反复地说,代理通过检查 HTTP 方法来判断操作的安全性。只要通过 HTTP 方法表达的操作的目的与该操作的实现保持一致,操作就是安全的。
在实现中不要使用安全方法(如 GET 和 HEAD )进行不安全的操作(如,写数据),这点非常重要。[……] 因为 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 架构风格的关键原则。
您的见解呢?请一定在此处或在原帖中发表出来。
评论