与实体不对应的RESTful操作/服务?

时间:2011-06-22 00:14:27

标签: rest

我喜欢RESTful的简单性以及它如何避免像SOAP这样的普通“企业”系统,或DCOM和RPC的二进制硬度。

但REST似乎比更抽象的服务更适合数据库实体。我想知道你是否可以告诉我你是如何做这些情况的:

例如,假设我有一个用于普通数据库系统的RESTful Web服务(例如,乳品购物网站),所以我有/ products / eggs / battery和/ products / milk / skimmed

通过对/ products / eggs进行POST来实现INSERT。

但你怎么做“清除所有”命令? DELETE动词仅适用于单个实体。而“DELETE / products / milk”意味着删除“牛奶”产品类别本身,而不仅仅是牛奶类别中的所有产品。如果你想同时完成两件事怎么办?

我遇到的另一个问题涉及与实体无关的网络服务操作。例如,如果我正在为密码数据库设计一个Web服务,我会有“GET /passwords/stackoverflow.com”这样的操作,这很好,但我也有操作在入侵的情况下禁用该网站检测。在“旧学校”网络服务模式下,我有一个名为“disableWebsite”的方法,但是我不能创建一个名为“DISABLE”的HTTP动词和一个名为“/ website”的资源(所以请求将是“ DISABLE /网站“)。这里有什么解决方案?

最后,如何将HTML表单与RESTful协调? Web表单只能使用查询字符串或POST进行GET请求。如果我有搜索表单,我希望它请求“/ products / search / {query}”,但现在请求看起来像“/ products / search?query = {query}”。

3 个答案:

答案 0 :(得分:5)

我认为你应该停止将资源视为数据库实体的同义词。是的,它们通常是相关的,但资源实际上只是您域中的可寻址概念。我认为将资源视为您在使用浏览器时在网络上看到的内容(列表,项目,帖子,评论,图片等等)会更有用。

  

但你怎么做“全部清除”命令?

我不确定为什么DELETE / products / milk意味着删除了牛奶类别本身,但如果您愿意:

DELETE /products?category=milk

DELETE并不意味着删除单个数据库实体。它意味着删除单个资源。并且“/ products?category = milk”(或“/ products / milk”,就此而言)标识单个资源。如果你可以获得它,你可以删除它。

  

如果你想完成两件事怎么办?

这个怎么样?

DELETE /product-categories/milk

Ruby on Rails受欢迎的一个技巧是为任何PUT / POST / DELETE操作提供一个表单(使用GET)。因此,对于这些删除,您可能需要提供如下表单:

GET /product-categories/milk/delete

以这种形式(想想HTML),您可以询问您的用户是否可以删除整个类别。(请不要注意HTML表单与RESTful Web服务不兼容的概念.HTML是一种非常成功的与网络资源交互的格式,精心设计的AJAX应用程序可能首先作为精心设计的HTML应用程序工作。需要制定一些细节来支持浏览器和其他客户端,但他们都是合法的REST客户。)

  

如何禁用网站?

有很多方法可以做到这一点。只需对带有禁用标志的/sites/stackoverflow.com进行PUT即可。

  

最后,如何将HTML表单与RESTful协调?

您无法从浏览器中真正执行HTTP PUT或DELETE,但您可以在表单中提供隐藏字段以伪造它:

<input type="hidden" name="_method" value="PUT" />

只要您的路由引擎支持它,这是将浏览器帖子路由到适当的处理程序的好方法(我也看到人们对非HTML客户端使用X-HTTP-Method-Override标头而不是完整的支持HTTP动词。)

如果您对挖掘感兴趣,我建议Web Services Cookbook作为入门者。另外,请查看Richardson Maturity Model。请记住,REST就像网络的其他部分一样。没有这些链接就不会有用。为您的客户提供一种出行方式。

<a href="/products/milk/delete" rel="delete" />

<atom:link href="/products/milk/delete" rel="delete" />

答案 1 :(得分:4)

RESTful系统与“资源”交互,这些“资源”与实体的标准概念无关 “资源”是一个非常模糊的概念,有一些严格的规则。我喜欢将资源视为任何有用的概念,可以帮助客户做他们需要做的事情。 因此,如果您需要删除一堆实体,那么创建一个表示“一堆实体”的资源,然后在其上使用DELETE方法。

设计宁静系统的真正诀窍是停止尝试为特定资源分配重要性,但要为两个资源之间的关系分配重要性。想想HTML的工作原理。您下载页面,并有一个样式表链接。 rel =“stylesheet”定义了你在href URL末尾找到的含义 如果要禁用网站,请访问网站资源并使用与rel =“disabler”链接中的URL。 RESTful设计是关于定义通过链接相互关联的资源。有些链接仅用于检索信息,其他链接实际用于更改资源状态。

资源必须遵循的严格规则是资源必须具有标识符(例如URL),您可以仅通过“表示”与该资源进行交互那资源。这些陈述可以是各种不同的格式。

对于HTML表单,忘记了URI的样子,使用查询字符串参数与路径参数一样RESTful。 HTML Forms允许您执行GET和POST,即安全操作和不安全操作。这对任何人来说都足够了。确实DELETE和PUT可能很有用,但实际上,与超媒体相比,这些额外方法给RESTful系统带来的好处非常小。

答案 2 :(得分:2)

  

但你怎么做“清除所有”命令? DELETE动词仅适用于单个实体。

假。

  

“DELETE / products / milk”意味着删除“牛奶”产品类别本身,而不仅仅是牛奶类别中的所有产品。

正确。

  

如果你想完成两件事怎么办?

/cart/milk/上的DELETE有什么问题?

  

在“老派”网络服务模式下,我有一个名为“disableWebsite”的方法,

什么?

  

但是我无法创建名为“DISABLE”的HTTP谓词和名为“/ website”的资源(因此请求将为“DISABLE / website”)。这里有什么解决方案?

POST。 POST到/passwords/stackoverflow.com/disable/实体(passwords/stackoverflow.com)在其中包含“禁用”和“启用”子实体。您可以发布任何一个来更改父实体的状态。

  

如果我有搜索表单,我希望它请求“/ products / search / {query}”

这就是为什么大多数RESTful Web服务都是用Javascript或Flex或类似的东西编写的。

RESTful Web服务和“本机”HTML表单并不真正兼容。他们不应该是。