2010-05-18 30 views
4

有一些文件系统的基本操作(如:lsrm)的明显同行,但你会如何实现不直截了当REST风格的动作,如cpmv如何使用REST为文件系统操作建模?

作为对How to implement copy paste of a resource in REST?问题的回答,实施cp的首选方式包括获取资源,删除它并将其重新以新名称重新寄回。

但是如果我需要有效地做到这一点呢?例如,如果资源的规模会很大?我将如何消除资源负载的多余传输给客户端并返回到始发服务器?

下面是一个例子。我有一个资源:

 
/videos/my_videos/2-gigabyte-video.avi 

,我希望它复制到新资源:

 
/videos/johns_videos/copied-2-gigabyte-video.avi 

我怎么会执行复制,移动或其他文件系统操作使用RESTful方式?还是有一个正确的方法?我做错了什么吗?

回答

3

[...实施 CP将包括获取资源, 删除它,并用新名称重新装回去 的首选方式。采用上面的方法

的一个问题缺乏原子性和一致性。由于每个操作(GET,DELETE和PUT)都是通过HTTP进行的(这本身就是无状态的),所以服务器不能执行原子性。出于任何原因,客户端可能会在最后一步之前的任何步骤之后中止,并且会导致服务器的数据状态不一致。

一种可能的方法:

  • 如果资源文件(我猜,他们是你的情况)我会探索利用WebDAV的选项。
  • 如果WebDAV是不是一种选择 -
    • 在服务器上创建一个控制器对象来管理复制和移动操作,客户可以张贴到像/视频/的my_videos/[VIDEO_ID] /复制
    • 在你的回应,你可以指定的URI复制资源,在该行:

HTTP/1.1 201创建

内容类型:视频/ X-msvideo

位置:/视频/ johns_videos/8765

注:我更喜欢发送ID背部和资源ID而不是一些工作一样

地点: /videos/johns_videos/copied-2-gigabyte-video.avi

移除操作非常类似,但服务器可能接受目标资源。例如:

http://example.com//videos/johns_videos/8765/move?destination=[destination]

可以扩展上述方法,使得所述服务器发送上次修改标签到客户端和客户端发送与它的请求一起。仅当该值仍然一致时,服务器才会执行复制/移动操作。这将解决您的复制/移动操作仍在进行时正在更改的资源的并发问题。

+0

我喜欢你的方法 - 我会看看我是否可以使用Webdav。在另一种方法中,URL/video/my_videos/[video_id]/copy中的名为copy的资源不会将操作编码到与REST原则相反的URL中吗? – massive 2010-05-19 07:41:41

+0

@massive - 1.当然看看WebDAV是否适用于这种情况(我认为这是定制的) 2.作为资源复制/移动不违反任何REST原则。将资源仅仅视为“事物”或领域对象只会在一定程度上带我们。为了更实际的目的,您需要将处理功能作为资源(例如:计算保费,两个银行账户之间的转账金额等)。 这是一个在RESTful Web Services Cookbook(O'reilly)中讨论得很好的模式。如果您有任何疑问,我很乐意进一步讨论。 – 2010-05-19 12:11:12

+0

我在这里看不到很多RESTful(也许没关系)。没有涉及的超媒体(没有链接要遵循),你需要带外信息才能知道../copy URI甚至存在。 – Gandalf 2010-05-19 15:42:19

0

在我看来,视频是一种资源。所以这个资源有一个路径。如果您执行更改资源路径的UPDATE会怎么样?

然后,在你的代码中,如果它改变了路径,你只需要移动文件。

+0

你会如何建议修改与更新路径?当然,如果我的资源在它的表示中有路径,那么我可以改变表示,但是如果没有,那么我就没有想法。 – massive 2010-05-19 07:56:51

0

这样做的一种方法是制定您的PUT/POST请求,以便您可以提供实际数据或提供资源的URL,可能使用选项来创建硬链接或符号链接。如果给定的URL托管在您自己的系统上,那么您可以简单地将内部指向同一个文件,可能保留一点“复制写入”或沿着这些行的某些内容以使其高效。

1

您可能会公开一个新的服务,它需要(POST)一个简单的xml文档来概述您想要执行的操作。

<move> 
    <target>/videos/my_videos/2-gigabyte-video.avi</target> 
    <destination>/videos/johns_videos/copied-2-gigabyte-video.avi<destination> 
<move> 

然后,此服务可以返回一个URI,客户端可以去检查操作的状态。然后,客户端可以与新资源进行交互,以便在尚未处理的情况下取消移动,或者检查是否成功。

+0

但是,这实际上并不意味着您将该操作的含义编码到消息中? – massive 2010-05-19 06:01:12

+0

完全没有。你的信息正在改变系统的状态,这实际上是HATEOAS的定义。你会如何编写一个没有意义的信息? – Gandalf 2010-05-19 13:13:01

+0

好吧,我明白你的观点。我只是不太喜欢在消息中对动作进行编码,因为它让我想起了RPC风格的Web服务 (例如SOAP),其中将操作(移动)封装在信封中并将其发送到通用端点。理解这种消息的意义的唯一方法是需要解析它并理解它的语义,这看起来不是很RESTful。如果我只使用四个基本的HTTP动词,那么可能还没有完美的解决方案。 – massive 2010-05-19 13:46:59

0

REST不限于HTTP!最好的方法是使用webdav解决您的问题。

4

我不相信任何给定的答案是RESTful。这是我会做的。

用于复印:

PUT /videos/johns_videos/copied-2-gigabyte-video.avi 
HOST: www.server.com 
Content-Location: /videos/johns_videos/2-gigabyte-video.avi 
[empty-body] 

把内容的在位置(/videos/johns_videos/2-gigabyte-video.avi)在(/videos/johns_videos/copied-2-gigabyte-video.avi) 。

移动将是一个带有删除的副本,为了检查副本和删除之间的一致性,您将需要使用在PUT的响应中给出的修订号。

PUT /videos/johns_videos/copied-2-gigabyte-video.avi 
HOST: www.server.com 
Content-Location: /videos/johns_videos/2-gigabyte-video.avi 
[empty-body] 

    201 Created 
    ETag: "3e32f5a1123afb12" (an md5 of the file) 
    Location: /videos/johns_videos/copied-2-gigabyte-video.avi 
    [empty-body] 

DELETE /videos/johns_videos/2-gigabyte-video.avi 
HOST: www.server.com 
If-Match: "3e32f5a1123afb12" 
[empty-body] 

    204 No Content 
    [empty-body] 

为什么这个RESTful?

  • 不追加“移动”或“复制”到URI(这是RPC)
  • 它使用PUT(POST是追加到集合,目标URI尚不完全清楚)
  • 它不使用RPC(而不是REST)发送的“命令”(例如XML指令)。
  • 不理解下划线存储 - 客户端不关心硬/软链接或写入副本优化,也不应该了解它们。

迈克·布朗

相关问题