2011-01-12 102 views
4

我对REST原理相当熟悉,并已阅读相关论文,维基百科条目,一堆博客文章和有关此主题的StackOverflow问题,但仍未找到常见情况的直接答案:如何获取REST风格的只读vs可编辑资源?

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

如果我的用户跟着GET /resource/<id>的链接,那应该足以表明他/她需要只读表示。但是如果我需要将可编辑表单服务器起来,那么这个URL是什么样子的? GET /resource/<id>/edit是显而易见的,但它在URL中包含一个动词。改为GET /resource/<id>/editable解决了这个问题,但在表面上看似肤浅。这一切是否存在 - 将动词改为形容词?

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

请注意,即使在可编辑状态下,我还没有做任何更改;大概当我再次将资源提交给Web服务器时,我会将其发布。但为了让我可以稍后POST,服务器必须第一个提供一个特定的表示。

我想另一个办法是必须在集合级别不同的资源: GET /read-only/resource/<id>GET /editable/resource/<id>GET /resource/read-only/<id>GET /resource/editable/<id> ...但是这看起来很丑陋给我。

想法?

回答

6

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

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

1

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

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

如果您想要对有问题的资源创建锁定,请使用POST写入资源(或资源的容器,资源ID编码在POST的主体中),并让服务器创建一个锁作为新资源,并返回该资源的ID作为对POST的响应。 (身份验证问题超出了您的问题或此答案的范围)

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

+0

是的,我知道,这就是我的问题的关键。我给出了PUT和POST的例子,我认为这些方法不会起作用,即使我可以找到它们的边缘语义原因。所以,回到GET。我如何区分可编辑和不可编辑表示? – Val 2011-01-12 01:15:03

+0

他们为什么会有不同? (在GET的情况下) – 2011-01-12 01:16:57

+0

他们会有所不同,因为需要可编辑。这意味着我需要渲染一个表单。我需要知道我是否在表单中呈现请求的资源。我如何知道如何呈现资源? – Val 2011-01-12 01:21:51

2

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

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

+0

是的,这正是会发生的事情。我将从这些资源集合的列表中获取单个资源,并且该列表将通过基于并表达目标资源状态的链接超链接到每个单独的资源。因此,该集合将具有诸如“GET/resources/resource/23”和“GET/resources/resource/24/edit”的链接。只是我读到的所有东西在网址中都有一个动词(例如“编辑”)是一种难闻的气味。我应该克服它吗? – Val 2011-01-12 01:19:19

+0

菲尔丁有一个博客? +11111111 – Anders 2011-01-12 01:20:37

3

在REST中,编辑现有资源是由客户端完成GET资源的表示,对表示进行更改,然后将新表示重新传递给服务器。

所以只是阅读资源的REST客户端程序会做:

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

并以编辑该资源:

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

通常同时更新通过让处理假设它代表一个更新的状态,最后一个到达服务器的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的限制。如果使用Restlet(用于Java)等服务器端REST框架,它支持“重载POST”的概念,您可以在其中使用POST,但是可以使用查询字符串参数(如method = PUT或method = DELETE)。如果你正在编写你自己的服务器端组件,他们也可以使用这个技巧。

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

请务必阅读Richardson和Ruby的Restful Web Services(O'Reilly)。这非常有帮助。

3

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

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

0

我想你的问题可能是“如何识别在PUT动作中使用GET动作返回的只读表示”?您可以这样做:

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

从PUT解析请求XML后,您可以忽略只读部分并处理其他部分。在响应中,返回200状态并留言说只读部分被忽略。 这是您的预期吗?