views:

78

answers:

5

There are obvious counterparts for some of file systems' basic operations (eg. ls and rm), but how would you implement not straightforwardly RESTful actions such as cp or mv?

As answers to the question How to implement copy paste of a resource in REST? suggest, the preferred way of implementing cp would include GETting the resource, DELETing it and PUTting it back again with a new name.

But what if I would need to do it efficiently? For instance, if the resource's size would be huge? How would I eliminate the superfluous transmission of resource's payload to client and back to the originating server?

Here is an illustration. I have a resource:

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

and I want copy it into a new resource:

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

How would I implement the copy, move or other file system actions the RESTful way? Or is there even a proper way? Am I doing it all wrong?

A: 

To my opinion, the video is a resource. So this resource has a path. what if you do an UPDATE that change the resource path ?

Then, in your code, if it changes the path, you just have to move the file.

dzen
How would you suggest to change the path with UPDATE? Of course if my resource would have path in it's representation, then I could change the representation, but if not, then I'm out of ideas.
massive
A: 

One way to do this is to formulate your PUT/POST requests such that you can either give the actual data or give the URL of the resource, possibly with the option to make a hard or symbolic link. If the given URL is hosted on your own system, then you can simply point internally to the same file, possibly keeping a bit for "copy-on-write" or something along those lines in order to make it efficient.

Michael Aaron Safyan
+3  A: 

[...the preferred way of implementing cp would include GETting the resource, DELETing it and PUTting it back again with a new name.]

One problem with the above approach is lack of atomicity and consistency. Since each of the operations (GET, DELETE and PUT) happen over HTTP (which is stateless inherently) the server cannot enforce atomicity. For any reason, the client may abort after any step before the last step and that would leave the server with an inconsistent state in terms of its data.

A possible approach:

  • If the resources are documents (which I guess, they are in your case) I'd explore the option of using WebDAV.
  • If WebDAV is not an option --
    • create a controller object on the server to manage copy and move operations, client can POST to something like /videos/my_videos/[video_id]/copy
    • In your response you can specify the URI to the copied resource, in the lines of:

HTTP/1.1 201 Created

Content-type:video/x-msvideo

Location:/videos/johns_videos/8765

Note: I prefer sending an ID back and working with resource IDs rather than something like

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

Move operation is pretty similar except that the server may accept a destination resource. Example:

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

You can extend the above approach such that the server sends a Last-Modified tag to the client and client sends that along with its request. The server will perform the copy/move operations only when that value is still consistent. This will address concurrency issues with the resource being changed while your copy/move operations are still in progress.

Surya Suravarapu
I like your approach - I will see if I can utilize Webdav. On your other approach, wouldn't a resource named copy in the URL "/videos/my_videos/[video_id]/copy" encode the operation in to the URL contrary to REST principles?
massive
@massive --1. Certainly see if WebDAV works for the situation (which I think is tailor-made)2. Copy/Move as a resource doesn't violate any REST principles. Thinking resources as "things" or domain objects alone will take us only to certain extent. For more practical purposes you need processing functions as resources (e.g: calculate premium, transfer amount between two bank accounts, etc.).This is a pattern discussed quite well in the RESTful Web Services Cookbook (O'reilly). I would be glad to discuss further if you have any concerns.
Surya Suravarapu
I don't see much that is RESTful here (and maybe that's OK). There is no hypermedia involved (no links to follow) and you have out of band info being needed to know that a ../copy URI even exists.
Gandalf
+1  A: 

You could expose a new service that takes (POST) a simple xml doc that outlines what you want to do.

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

Then this service could return a URI where the client can go and check the status of the operation. Then the client could interact with that new resource to say cancel the move if still pending, or check on it's success.

Gandalf
But wouldn't that actually mean that you are encoding the meaning of the operation into the message?
massive
Not at all. Your message is changing the state of the system, it's really the definition of HATEOAS. How would you ever compose a message that had no meaning?
Gandalf
Okay I see your point. I'm just uneasy to encode actions within the messages, since it reminds me about RPC-style web services(Eg. SOAP), where you encapsulate the operation (move) in an envelope and send it to a generic endpoint. The only way understand the meaning of such message would require parsing it and understanding it's semantics, which doesn't seem very RESTful. Then again, there might not be perfect solution if I were to use only the four basic HTTP-verbs.
massive
It's really no different then the class "RESTbucks - How to Order a Cup of Coffee RESTfully" (or whatever t's called) example that everyone always quotes. You're submitting a job to a queue, getting back a response (and links to other resources). Your client just needs to understand the hypermedia format you define and then follow the linked data graph to the outcome.
Gandalf
A: 

REST is not limited to HTTP! The best way would be to use webdav for your problem.

deamon