First of all, i would like to Thank #Darrel Miller. The below question raised from his answer in RESTful copy/move operations?.
I am trying to construct a restFul service, with multiple resource and one resource in that is - for copying file from one location to another location under same parent directory.
Here are my confusion:
Which method to choose for it? POST or PUT.
Can we go with URL Params or through Payload?
If it is URL Params how it should looks like?
And if suppose i need to do this for list of files, Is it still good to go with URL Params?
These are my params
sourceLocation
destLocation
fileName
Thanks in advance!
Related
Im currently working on a more or less RESTful webservice, a type of content api for my companys articles. We currently have a resource for getting all the content of a specific article
http://api.com/content/articles/{id}
will return a full set of article data of the given article id.
Currently we control alot of the article's business logic becasue we only serve a native-app from the webservice. This means we convert tags, links, images and so on in the body text of the article, into a protocol the native-app can understand. Same with alot of different attributes and data on the article, we will transform and modify its original (web) state into a state that the native-app will understand.
fx. img tags will be converted from a normal <img src="http://source.com"/> into a <img src="inline-image//{imageId}"/> tag, samt goes for anchor tags etc.
Now i have to implement a resource that can return the articles data in a new representation
I'm puzzled over how best to do this.
I could just implement a completely new resource, on a different url like: content/articles/web/{id} and move the old one to content/article/app/{id}
I could also specify in my documentation of the resource, that a client should always specify a specific request header maybe the Accept header for the webservice to determine which representation of the article to return.
I could also just use the original url, and use a url parameter like .../{id}/?version=app or .../{id}/?version=web
What would you guys reckon would be the best option? My personal preference lean towards option 1, simply because i think its easier to understand for clients of the webservice.
Regards, Martin.
EDIT:
I have chosen to go with option 1. Thanks for helping out and giving pros and cons. :)
I would choose #1. If you need to preserve the existing URLS you could add a new one content/articles/{id}/native or content/native-articles/{id}/. Both are REST enough.
Working with paths make content more easily cacheable than both header or param options. Using Content-Type overcomplicates the service especially when both are returning JSON.
Use the HTTP concept of Content Negotiation. Use the Accept header with vendor types.
Get the articles in the native representation:
GET /api.com/content/articles/1234
Accept: application/vnd.com.exmaple.article.native+json
Get the articles in the original representation:
GET /api.com/content/articles/1234
Accept: application/vnd.com.exmaple.article.orig+json
Option 1 and Option 3
Both are perfectly good solutions. I like the way Option 1 looks better, but that is just aesthetics. It doesn't really matter. If you choose one of these options, you should have requests to the old URL redirect to the new location using a 301.
Option 2
This could work as well, but only if the two responses have a different Content-Type. From the description, I couldn't really tell if this was the case. I would not define a custom Content-Type in this case just so you could use Content Negotiation. If the media type is not different, I would not use this option.
Perhaps option 2 - with the header being a Content-Type?
That seems to be the way resources are served in differing formats; e.g. XML, JSON, some custom format
I have a question. For a rest service API designing, we can have a post method with parameters. There are four places to put my parameters.
1, we can pass it as URI template, I think if the variable is a resource, we have to put it there.
2, we can put it to the header of the request, I guess "version" is a good choice.
3, we can put it to the post request body, I mean the real parameters we want to execute the method on server.
4, we can put it as a query string, such as /sample.com/orders?id=1025.
In my mind, the post and put is not suggest to put parameters in the query string as my fourth point indicated, I cannot remember where I got that, or I might misunderstand it. Please correct me if I'm wrong, and let me know how do you think about this.
Thanks,
I think I already figureout what I asked. Here is a related post, please refer that if anymore needs it.
Do HTTP POST methods send data as a QueryString?
Thanks,
I am using ember-rest in my application for persistence layer, and it has been working great. One of the resources that I am working with, requires some optional resource parameters. Looking at the ember-rest source code, I couldn’t find anything related to setting request parameters, but it is possible that I overlooked something.
My question is, does ember-rest provide a way to specify request parameters to be appended to the URL? If not, some advice about how I should add this functionality to ember-rest would be very appreciated.
For example, I am working with a resource called blocki which comes with the following REST api:
POST /api/apps/:app_id/blockies?parent=:parent_id
- default :parent_id=:app_id
- TODO: error if the blocki cannot be placed in :parent_id
PUT /api/blockies/:id
PUT /api/blockies/:id?parent=:parent_id
- update the blocki and reparent it
DELETE /api/blockies/:id
As you can see when I do a put request to update this resource I can optionally pass a parent_id if I want to update that. I want to achieve this using ember-rest.
You can completely customize the url for a resource or resource controller by overriding the _resourceUrl() method. For instance:
_resourceUrl: function() {
return this._super() + '?parent=' + this.get('parent_id');
}
I am trying to do authorization in away that only owners of the objects can edit them.
How can i get the ids of the objects being edited in the post call in my authorization method?
Eg: If someone PUTs to the url /api/v1/resource_name/1, I want to get '1'
Also, tastypie allows a collection of objects to be edited at one go. (http://django-tastypie.readthedocs.org/en/latest/interacting.html#updating-a-whole-collection-of-resources-put)
Is there a way for me to get a list of the objects being edited in any call?
Thanks!
I have been struggling with this as well. Right now, I determine the object by parsing request.path. I believe a more direct method (via the object parameter in Authorization() for example) will become available in 0.9.12 and beyond.
You might watch this question as well: How can I pass a detail object to custom authorization in tastypie?.
Good luck.
I am trying to design a RESTful filesystem-like service, and copy/move operations are causing me some trouble.
First of all, uploading a new file is done using a PUT to the file's ultimate URL:
PUT /folders/42/contents/<name>
The question is, what if the new file already resides on the system under a different URL?
Copy/move Idea 1: PUTs with custom headers.
This is similar to S3's copy. A PUT that looks the same as the upload, but with a custom header:
PUT /folders/42/contents/<name>
X-custom-source: /files/5
This is nice because it's easy to change the file's name at copy/move time. However, S3 doesn't offer a move operation, perhaps because a move using this scheme won't be idempotent.
Copy/move Idea 2: POST to parent folder.
This is similar to the Google Docs copy. A POST to the destination folder with XML content describing the source file:
POST /folders/42/contents
...
<source>/files/5</source>
<newName>foo</newName>
I might be able to POST to the file's new URL to change its name..? Otherwise I'm stuck with specifying a new name in the XML content, which amplifies the RPCness of this idea. It's also not as consistent with the upload operation as idea 1.
Ultimately I'm looking for something that's easy to use and understand, so in addition to criticism of the above, new ideas are certainly welcome!
The HTTP spec says if the resource already exists then you update the resource and return 200.
If the resource doesn't exist then you create it and you return 201.
Edit:
Ok, I misread. I prefer the POST to the parent folder approach. You could also refer to the source file using a query string parameter. e.g.
POST /destination/folder?sourceFile=/source/folder/filename.txt
To create a new resource you usually use POST. This should create a new resource on a URI creates by the Server.
POST /folders/42/contents/fileName
<target>newFile</target>
What REST says is that with POST the new Resource is located in a path determined by the server. This is how copy even works in the (windows) FileSystem. Consider you copy a file to a name that already exists, then the response of the above example could be:
<newFileLocation>/folders/42/contents/newFile-2</newFileLocation>
A move is then made by first copy then delete. You should not do these two actions in one request.
Edit:
I found the book RESTful Web Services Cookbook very good.
Chapter 11 handles the Copy method and recommends the following in 11.1:
Problem You want to know how to make a copy of an existing resource.
Solution Design a controller resource that can create a copy. The client makes a POST request to this controller to copy the
resource. To make the POST conditional, provide a one-time URI to the
client. After the controller creates the copy, return response code
201 (Created) with a Location header containing the URI of the copy.
Request POST /albums/2009/08/1011/duplicate;t=a5d0e32ddff373df1b3351e53fc6ffb1
Response
<album xmlns:atom="http://www.w3.org/2005/Atom">
<id>urn:example:album:1014</id>
<atom:link rel="self" href="http://www.example.org/albums/2009/08/1014"/>
...
</album>
REST is not limited to the default set of HTTP methods. You could use WebDAV in this case.
For the move part, just do a combo of Copy (PUT) then Delete if you want to keep it simple.
For moving, you could
a). copy via PUT with a custom source header followed by a DELETE on the source.
b). DELETE source with a custom move header.
I prefer the latter because it can be atomic and it is clear to the client that the resource was removed from the original collection. And when it GETs the collection of its new location, it will find the moved resource there.