如何以REST样式获取只读vs可编辑资源?

时间:2011-01-12 01:00:50

标签: url rest

我对REST原则非常熟悉,并阅读了相关的论文,维基百科条目,一堆博客文章和StackOverflow关于这个主题的问题,但仍然没有找到一个简单的常见案例答案:

我需要请求显示的资源。根据资源的状态,我需要呈现只读或可编辑的表示。在这两种情况下,我都需要获取资源。如何构建URL以获取只读或可编辑版本?

如果我的用户关注了GET /resource/<id>的链接,那么就足以向我表明他/她需要只读表示。但是,如果我需要为可编辑的表单提供服务,该URL看起来像什么? GET /resource/<id>/edit很明显,但它在URL中包含一个动词。将其更改为GET /resource/<id>/editable解决了这个问题,但处于看似肤浅的程度。这就是它的全部 - 将动词改为形容词吗?

如果我使用POST来检索可编辑版本,那么如何区分最初检索它的POST与保存它的POST?使用POST的我(弱)借口是检索可编辑的版本会导致服务器上的状态更改:锁定资源。但是,只有在我的要求是实现这样的锁定时才能成立,但情况并非总是如此。由于同样的原因,PUT失败了,在我正在运行的Web服务器上默认没有启用PUT,因此有实际原因不使用它(和DELETE)。

请注意,即使在可编辑状态下,我还没有进行任何更改;大概是当我再次将资源提交给Web服务器时,我会发布它。但为了获得我以后可以发布的内容,服务器必须首先提供特定的表示。

我想另一种方法是在集合级别拥有单独的资源: GET /read-only/resource/<id>GET /editable/resource/<id>GET /resource/read-only/<id>GET /resource/editable/<id> ......但这对我来说非常难看。

思想?

6 个答案:

答案 0 :(得分:6)

1)拥有两个不同的资源是完全有效的,一个用于查看,另一个用于编辑某些域概念。请注意,因为它们是REST的两个不同的URI,所以它们是两种不同的资源。人们经常将资源与域对象混为一谈。这就是为什么他们最终被卡住只做CRUD。

2)不要太挂在资源的名称上。重要的是你意识到URI指向的是“事物”,“资源”。如果您使用editable而不是edit对您更明显,那么请使用它。在您的URL中使用动词不会使您的应用程序出错,它只会使人类开发人员的可读性降低一些。使用URL中的动词尝试重新定义HTTP方法的语义,现在这违反了统一接口约束。

答案 1 :(得分:3)

在REST中,编辑现有资源是由客户端完成该资源的表示,更改表示,然后将新表示的PUT返回给服务器。

所以只需读取您的REST客户端程序将执行的资源:

GET http://www.example.com/SomeResource

编辑该资源:

GET http://www.example.com/SomeResource
... edit it ...
PUT http://www.example.com/SomeResource

通常通过让最后一个到达服务器的PUT覆盖之前的PUT来处理同时更新,假设它代表一个较新的状态。但在你的情况下,你想要防范这一点。

仔细考虑@Jason的建议,为每个主要资源维护一个可选的并行锁资源。您的客户端将首先创建锁,进行编辑,然后删除锁。如果随后进行锁定的用户从未保存任何更改,则系统需要自动释放锁定。这看起来像是:

GET http://www.example.com/SomeResource     
... user presses an edit button ...
PUT http://www.example.com/SomeResource/lock    
... user edits the resource's representation ...
PUT http://www.example.com/SomeResource
DELETE http://www.example.com/SomeResource/lock

如果用户尝试编辑被其他人锁定的资源,则需要进行一些适当的错误处理。

听起来你觉得你受到当前HTML限制的束缚。如果您使用服务器端REST框架(如Restlet(适用于Java)),它支持“重载POST”的概念,您可以在其中使用POST,但可以使用方法= PUT或method = DELETE等查询字符串参数。如果你正在编写自己的服务器端组件,他们也可以使用这个技巧。

您也可以在HTML级别上玩弄技巧。例如,您的页面可以有一个最初显示的只读部分,一个最初未显示的输入表单。当用户按下编辑按钮时,您的JavaScript会隐藏只读部分并显示输入表单。

一定要阅读Richardson和Ruby的Restful Web Services(O'Reilly)。这非常有帮助。

答案 2 :(得分:3)

我不认为返回表单或只是值取决于REST服务器,而是客户端的责任。资源是否可可编辑是资源的属性,而不是URL定义的内容。

换句话说:获取资源的URL是GET /resource/<id>。这有一个可编辑的属性。如果用户想要表单,则可以从同一URL检索资源并填充表单。客户端可以比PUT / POST更改。

答案 3 :(得分:2)

  

如何构建URL以获取只读或可编辑的版本?

这里存在一个潜在的问题,即您首先构建URL - 将ID附加到硬编码的URL不是REST。 Roy Fielding has written about this very mistake。无论哪个文档提示您编辑资源,都应包含该资源的可编辑变体的URI。您遵循该URI,无论/resource/editable还是/editable/resource是否超出REST的范围。

答案 4 :(得分:1)

  

如果我使用POST来检索可编辑版本,那么如何区分最初检索它的POST与保存它的POST?

您执行GET(不是POST)来读取资源,并执行POST(或PUT)来编写资源。

如果要在相关资源上创建锁定,请使用POST写入资源(或资源的容器,并在POST正文中编码资源ID),并让服务器创建锁定< em>作为新资源,并返回该资源的ID作为对POST的响应。 (认证问题超出了您的问题范围或此答案)

然后解锁,请使用锁定资源上的DELETE或POST到锁的容器。

答案 5 :(得分:0)

我猜你的问题可能是“如何识别在PUT操作中通过GET操作返回的只读表示?”。你可以这样做:

<Root>
<readonly>
<p1><p1>
...
<readonly>
<others>
...
<others>
<Root>

从PUT解析请求XML后,您可以忽略只读部分并处理其他部分。在Response中,返回200状态并留下一条消息,说明readonly中的部分被忽略。 这是你的期望吗?