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?
I dont believe any of the given answers are RESTful. Here is what I would do.
For Copy:
PUT /videos/johns_videos/copied-2-gigabyte-video.avi
HOST: www.server.com
Content-Location: /videos/johns_videos/2-gigabyte-video.avi
[empty-body]
PUT the content's at location (/videos/johns_videos/2-gigabyte-video.avi) at (/videos/johns_videos/copied-2-gigabyte-video.avi).
A move would be a copy with a delete, to check for consistency between the copy and delete you will need to use a revision number which is given to you on the response of the 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]
Why is this RESTful?
Mike Brown
[...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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With