I'm designing a restful api, and trying to really do it right for the first time.
I've defined some nested resources (comments in a blog post), and that choice mirrors the fact that comments are nested within the blog post document in mongo.
I'm not interested in serving individual comments out of context, so I've deferred implementing GETs for the nested resources. However, it makes sense to implement POSTing to the comments collection, and PUTting to a comment uri.
Specific questions:
1) Does it make sense to respond to a POST with a 201 and a Location header set to the parent resource? If not, how do I communicate the parent location to inform navigation choices on the client?
2) Similar question for PUT, how do I best communicate to the client that it should look to the parent resource to locate its update? (preferably without the client having to make assumptions about my uri scheme). Is the Location header reasonable on a 200?
Although I have never done it myself, I have heard of people using the Content-Location header for this purpose. Content-Location is used to identify the location of the resource that is represented by the returned entity.
In the case of your PUT and POST, you may not actually want to return the entire blog post, so I'm not sure how valid it is to return a Content-Location header even when you are not returning a representation in the response.
Having said that, I can't think of any negative effects, so here is what I'm suggesting:
PUT /Blog/343/Comment/23
=>
200 OK
Content-Location: /Blog/343
POST /Blog/343/Comments
=>
201 Created
Location: /Blog/343/Comment/24
Content-Location: /Blog/343
Related
I was asked below question in the Interview -
If you are hitting the same request with PUT and with POST http method then what will be the difference in payload?
Considering I don't have much experience working in REST, I didn't even know what payload is. I tried googling but didn't find anything conviencing.
Can anyone help?
according to this page restfulapi.net the PUT request should refer to already existing item (for example in a database connected). In other words, it is meant to update existing item. So the payload don't have to contain all the attributes of the item, just those you want to update.
On the other hand POST is meant to insert new item. This means that the payload should contain (almost) everything.
Thing is, if you send more same PUT requests, the item should remain equivalent to the situation with just one PUT send.
If you send two same POST requests then two new same items (with different ids) will be created. This means that POST requests are not idempotent.
Edit: here might be help too.
I didn't even know what payload is.
The interviewer is probably referring to the message-body of the HTTP Request (see RFC 7230).
If you are hitting the same request with PUT and with POST http method then what will be the difference in payload?
This is probably an attempt to explore whether you understand the difference in semantics between the HTTP POST method and the HTTP PUT method.
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
Think "save file".
The instructions for POST are a lot less specific
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
If that seems vague... you're right! The message-body of a POST request can mean almost anything. POST is the "junk drawer" of HTTP methods - anything not worth standardizing goes there.
I'm writing a stateless API. You send it a document, it processes the document, and then returns the processed document. I'm struggling to understand how the RESTFUL rules apply. I'm not retrieving data, creating data or updating data on the server. There is no data on the server. What do I need to use in this case as the http method and why?
Good news - you are right that it is confusing.
Nothing on the server changes in response to the request. That suggests that the request is safe. So GET is the natural choice here... BUT -- GET doesn't support message payloads
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
HEAD, the other ubiquitous safe method, has the same problem (and is unsuitable when you want to return a document in any case).
The straight forward thing to do at this point is just use POST. It's important to realize that POST doesn't promise that a request is unsafe, only that it doesn't promise that it is safe -- generic components won't know that the request is safe, and won't be able to take advantage of that.
Another possibility is to look through the method registry, to see if somebody has already specified a method that has the semantics that you want. Candidates include SEARCH and REPORT, from the WebDAV specifications. My read of those specifications is that they don't actually have the right semantics for your case.
A Lot of ways to do what you want. But here is a small guideline.
I would create an endpoint that receives the document:
/receive_document
with a 'POST' method. Since you are 'sending' your document to the server
I would create an endpoint that serves up the processed document:
/processed_document
with a 'GET' method. Since you want to retrieve / see your document from the server?
The problem that you are trying to solve is mainly related to the document size, and processing time before returning the response.
Theorically, in order to use a restful approach, you have an endpoint, like yourhost.com/api/document-manager (it can be a php script, or whatever you are using as backend).
OK, so instead of naming the endpoint differently for each operation type, you just change the HTTP method, I'll try to make an example:
POST: used to upload the document, returns 200 OK when the upload is completed.
GET: returns the processed document, you can also return a different HTTP code, in case the document is not ready or even different if the document hasn't been uploaded. 204 no content or 412 precondition failed can be good candidates in case of unavailable document. I'm not sure about the 412, seems like it's returned when you pass a header in the request, that tells the server which resource to return. In your case, I think that the user processes one document at time. But to make a more solid api, maybe you can return an ID token to the user, into the POST response, then forward that token to the GET request, so the server will be able to know exactly which file the user is requesting.
PUT: this method should be used when updating a resource that has been already created with POST
DELETE: removes a resource, then return 204 or 404
OPTIONS: the response contains the allowed methods on this endpoint. You can use it to know for example which privileges has the currently logged user on a resource.
HEAD: is the same as a GET call, but it shouldn't return the response body. This is another good candidate for you to know when the document has been processed. You can upload with POST, then when the upload is done, start some kind of polling to the same endpoint with the HEAD method, finally when it will return "found", the polling will stop, and make the final GET call, which will start the download of the processed document.
HTTP methods are a neat way of managing HTTP communications, if used properly are the way to go, and easily understandable by other developers. And not to forget, you don't have to invent lots of different names for your endpoints, one is enough.
Hope that this helped you a little... But there are loads of guides on the net.
Bye!
I am designing a RESTful api for coupon redemption.
Each coupon can be redeemed only once, after redemption the coupon is on longer valid.
(POST) /coupons/{couponCode}/redeem
seems violate the RESTful guidelines since redeem is a verb.
can I just change redeem to redemption?
or can I just use
(POST) /coupons/{couponCode}?
btw I am not quite sure why use POST instead of PATCH, is it because of PATCH is idempotent and POST is not? I mean, when the coupon is redeemed for the first time, it will be marked as redeemed in database, but once it's done, the same request won't update this value anymore.
seems violate the RESTful guidelines since redeem is a verb
REST doesn't care what spelling you use for your resource identifiers.
So all of these choices are fine
POST /coupons/{couponCode}/redeem
POST /coupons/{couponCode}
POST /{couponCode}/redeem
POST /i/am/a/banana
POST /4ccd2f6f-a81e-4b70-b45c-20ce9f8732b5
Identifier spelling conventions are like variable naming conventions; they exist only to ease the burden of people, and are subject to local convention. The machines don't care.
The thing that matters is that the target uri used for your change matches the identifier of the resource in the cache that you want to invalidate.
I am not quite sure why use POST instead of PATCH, is it because of PATCH is idempotent and POST is not?
No. The difference is that PATCH promises that the payload is a patch document, which is to say a representation of a set of edits to the representation of "the" resource, whereas POST just says "this is a message to be processed by the resource".
(Both POST and PATCH are not idempotent, as it happens.)
Imagine a document store, where the documents are about one terabyte in size. You might want to change one of those documents. The natural way to do it is to GET the current representation, make your changes, and then PUT your version of the document back. But if your change is very small, then there's a lot of wasted work carrying duplicated copies of the document around.
So instead, we use PATCH, so that we can instead copy a small representation of the edit, rather than the full document.
POST is more general -- it's an unsafe message with a body, and that's pretty much all it promises. That body might be a new representation of the resource, or a patch to be applied to the current representation, or something entirely different.
why use redeem doesn't violate REST? shouldn't be verbs only HTTP methods?
Because REST is an architectural style, and it says that resource identifiers should be URL (RFC 1738) -- although these days that is generally understood to mean URI (RFC 3986) -- or URN (RFC 8141).
If you look at RFC 3986, I think you will find that the word "verb" doesn't appear anywhere in the document. You can review the ABNF rules for interpreting URI, and there is nothing about verbs in there anywhere.
REST doesn't care -- the URI is, in its primary use case, just an opaque sequence of bytes that are used by the client.
For example, try clicking on this link in your browser, does it work?
https://www.dictionary.com/browse/stop
The fact that "stop" happens to be a verb in English doesn't interfere with its function.
I also see some RESTful design guidelines suggest not to use verbs
Yup, the web is full of advice from people who don't understand the subject, or who do understand the subject and don't articulate it clearly, and so on.
REST doesn't offer enforce any particular URI design style.
In REST, the identifier is just an identifier, like a UUID, a hash signature, or a surrogate key. Within the context of an HTTP message, it doesn't mean anything, it's just a cache key. The message semantics come from the method, not the request-target.
GET /A/post HTTP/1.1
POST /B/get HTTP/1.1
DELETE /C/put HTTP/1.1
PUT /D/patch HTTP/1.1
There's no ambiguity in these request lines, the first token is the method that defines the semantics, the second token is just an arbitrary identifier. The machines will get them right every single time.
Recommended Viewing
Jim Webber, 2011
Stefan Tilkov, 2014
It would be better for you to use a url route where you expose the redeem action. This route should use the POST http request because you will modify a resource on the server, and will take as parameter your couponCode.
(POST) /coupons/redeem/{couponCode}
I don't think there is a difference between redeem and redemption. I think a verb like redeem is better to designate an action.
http PATCH or PUT request can be used too. As a convention, we use PATCH or PUT to update a resource after it has been created to change one of its attributes. If you are willing to use PATCH request to update let's say a coupon that you already created, then you can define a url route without the redeem action. The request body would contain the fields to be updated for the coupon object (for example status from "pending" to "redeemed")
(PATCH / PUT) /coupons/{couponCode}
Many use the following convention:
GET /objects (return list of objects)
GET /objects/id (return object)
PUT /objects/id (update object)
POST /objects (add object)
DELETE /objects/id (remove object)
Right now I have a REST service which creates a report via a POST:
POST http://myhost/reports
The report however is not persisted, and cannot later on be retrieved via a GET:
GET http://myhost/reports/{id}
Instead I return the report immediately in the response to the POST. Am I violating any REST principle here, e.g. anything a POST creates should always be accessible via a GET, or is this setup OK?
The POST method isn't a synonym to the create in CRUD. The POST method is used for any operation that isn't standardized, so as long as you document what it does, you're not violating REST, no matter what you do.
There's no such REST principle saying "anything a POST creates should always be accessible via a GET". This is a common misunderstanding due to conflating REST with CRUD. Read this answer for some clarification on that.
In informal language, what a POST says to the server is "take this data and apply it to the resource identified by the given URI, following the rules you documented for the resource media type."
No, you are not violating REST. As long as your interface is uniform it is up to you to determine what actions the urls of your API perform.
As part of your documentation you simply need to state which methods are valid for certain resources and which aren't. I really like to use the Twitter API as a good example of "What to do"
Example: Twitter REST API
POST statuses/update
does not create an object available for access at
GET statuses/update/3
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
So according to the HTTP standard this is okay.
I'm trying to find some info on the best and most common RESTful url actions.
for example, what url do you use for displaying the details of an item, for editing the item, updating, etc.
/question/show/<whatever>
/question/edit/<whatever>
/question/update/<whatever> (this is the post back url)
/question/list (lists the questions)
hmm. thanks to anyone helping out :)
Use URLs to specify your objects, not your actions:
Note what you first mentioned is not RESTful:
/questions/show/<whatever>
Instead, you should use your URLs to specify your objects:
/questions/<question>
Then you perform one of the below operations on that resource.
GET:
Used to obtain a resource, query a list of resources, and also to query read-only information on a resource.
To obtain a question resource:
GET /questions/<question> HTTP/1.1
Host: whateverblahblah.com
To list all question resources:
GET /questions HTTP/1.1
Host: whateverblahblah.com
POST:
Used to create a resource.
Note that the following is an error:
POST /questions/<new_question> HTTP/1.1
Host: whateverblahblah.com
If the URL is not yet created, you should not be using POST to create it while specifying the name. This should result in a resource not found error because does not exist yet. You should PUT the resource on the server first. You could argue that by creating a new question, you are also updating the /questions resource as it would now return one more question in its list of questions.
You should do something like this to create a resource using POST:
POST /questions HTTP/1.1
Host: whateverblahblah.com
Note that in this case the resource name is not specified, the new objects URL path would be returned to you.
DELETE:
Used to delete the resource.
DELETE /questions/<question> HTTP/1.1
Host: whateverblahblah.com
PUT:
Used to create a resource, or overwrite it, while you specify the resources URL.
For a new resource:
PUT /questions/<new_question> HTTP/1.1
Host: whateverblahblah.com
To overwrite an existing resource:
PUT /questions/<existing_question> HTTP/1.1
Host: whateverblahblah.com
...Yes, they are the same. PUT is often described as the 'edit' method, as by replacing the entire resource with a slightly altered version, you have edited what clients will GET when they next do.
Using REST in HTML forms:
The HTML5 spec defines GET and POST for the form element.
The method content attribute is an enumerated attribute with the following keywords and states:
The keyword GET, mapping to the state GET, indicating the HTTP GET method.
The keyword POST, mapping to the state POST, indicating the HTTP POST method.
Technically, the HTTP specification does not limit you to only those methods. You are technically free to add any methods you want, in practice though, this is not a good idea. The idea is that everyone knows that you use GET to read the data, so it will confuse matters if you decide to instead use READ. That said...
PATCH:
This is a method that was defined in a formal RFC. It is designed to used for when you wish to send just a partial modification to a resource, it would be used much like PUT:
PATCH /questions/<new_question> HTTP/1.1
Host: whateverblahblah.com
The difference is PUT has to send the entire resource, no matter how big it is compared to what's actually changed, whilst PATCH you can send just the changes.
Assuming /questions/10 is a valid question then the method is used to interact with it.
POST to add to it
PUT to create or replace it
GET to view/query it
and DELETE to well.. delete it.
The url doesn't change.
I'm going to go out on a limb and guess that you what you mean is what are standard controllers for MVC when you say "RESTful" urls, since your examples could be considered non-"RESTful" (see this article).
Since Rails really popularized the URL style you seem to be interested in, I offer below the default controller actions produced by the ScaffoldingGenerator in Ruby on Rails. These should be familiar to anyone using a Rails application.
The scaffolded actions and views are:
index, list, show, new, create, edit,
update, destroy
Typically you would construct this as:
http://application.com/controller/<action>/<id>
Here is a mapping of your current URLs using the REST principle:
/question/show/<whatever>
If you identify the question as a resource, then it should have a unique URL. Using GET to display it (retrieve it) is the common practice. It becomes:
GET /question/<whatever>
/question/edit/<whatever>
Now you want your user to have another view of the same resource that allows him to edit the resource (maybe with form controls).
Two options here, your application is an application (not a website), then you may be better using JavaScript to transform the resource into an editable resource ono the client side.
If this is a website, then you can use the same URL with additional information to specify another view, the common practice seems to be:
GET /question/<whatever>;edit
/question/update/<whatever> (this is the post back url)
This is to change the question, so PUT is the correct method to use:
PUT /question/<whatever>
/question/list (lists the questions)
The list of question is actually the parent resource of a question, so it naturally is:
GET /question
Now you may need some more:
POST /question (create a new question and returns its URL)
DELETE /question/<whatever> (deletes a question if this is relevant)
Tada :)
Your four examples could be:
GET /questions/123
POST (or PUT) /questions/123 q=What+is+the+meaning+of+life
POST (or PUT) /questions/123 q=What+is+the+meaning+of+life
GET /questions
To add a question:
POST /questions q=What+is+the+meaning+of+life
The server would respond:
200 OK (or 201 Created)
Location: /questions/456