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

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?

This entry was posted in SOA. Bookmark the permalink.

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s