创建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?

Advertisements
此条目发表在SOA分类目录。将固定链接加入收藏夹。

发表评论

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