I don't quite get how the HTTP verbs are defined as idempotent. All I've read is GET and PUT is idempotent. POST is not idempotent. But you could create a REST API using POST that doesn't change anything (in the database for example), or create a REST API for PUT that changes every time it is called.
Sure, that probably is the wrong way to do things but if it can be done, why is PUT labeled as idempotent (or POST as not) when it is up to the implementation? I'm not challenging this idea, I'm probably missing something and I ask to clear my understanding.
EDIT:
I guess one way to put my question is: What would be the problem if I used PUT to make a non-idempotent call and POST to do so?
You are right in pointing out there is nothing inherent within the HTTP protocol that enforces the idempotent attribute of methods/verbs like PUT and DELETE. HTTP, being a stateless protocol, retains no information or status of each request that the user makes; every single request is treated as independent.
To quote Wikipedia on the idempotent attribute of HTTP methods (emphasis mine):
Note that whether a method is idempotent is not enforced by the
protocol or web server. It is perfectly possible to write a web
application in which (for example) a database insert or other
non-idempotent action is triggered by a GET or other request. Ignoring
this recommendation, however, may result in undesirable consequences,
if a user agent assumes that repeating the same request is safe when
it isn't.
So yes, it is possible to deviate from conventional implementation, and rollout things like non-changing POST implementation, non-idempotent PUT etc. probably with no significant, life-threatening technical problems. But you might risk upsetting other programmers consuming your web services, thinking that you don't know what you're doing.
Here's an important quote from RFC2616 on the HTTP methods being safe (emphasis mine):
Implementors should be aware that the software represents the user in
their interactions over the Internet, and should be careful to allow
the user to be aware of any actions they might take which may have an
unexpected significance to themselves or others.
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects, so
therefore cannot be held accountable for them.
UPDATE: As pointed out by Julian, RFC 2616 has been replaced by RFC 7231. Here's the corresponding section.
So when you publish a web service as a PUT method, and I submit a request that looks like:
PUT /users/<new_id> HTTP/1.1
Host: example.com
I will expect a new user resource to be created. Likewise, if my request looks like:
PUT /users/<existing_id> HTTP/1.1
Host: example.com
I will expect the corresponding existing user to be updated. If I repeat the same request by submitting the form multiple times, please don't pop up a warning dialog (because I like the established convention).
Conversely, as a consumer of a POST web service, I will expect requests like:
POST /users/<existing_id> HTTP/1.1
Host: example.com
to update the corresponding existing user, while a request that looks like:
POST /users/<new_id> HTTP/1.1
Host: example.com
to raise an error because the URL doesn't exist yet.
Indeed, an implementation can do anything it wants. However, if that is incorrect according to the protocol spec, surprising things might happen (such as as library or intermediary repeating a PUT if this first attempt failed).
hope the link helps to you:HTTP Method idempotency
Be careful when dealing with safe methods as well: if a seemingly safe method like GET will change a resource, it might be possible that any middleware client proxy systems between you and the server, will cache this response. Another client who wants to change this resource through the same URL(like: http://example.org/api/article/1234/delete), will not call the server, but return the information directly from the cache. Non-safe (and non-idempotent) methods will never be cached by any middleware proxies.
Related
A few time ago I participate from a interview where had a question about REST modelling, and how the best way to implement it. The question was:
You have an REST API where you expose a method to consult the distance between two point, although you must save each request to this method to expose the request history.
And I was questioned about which HTTP method should be used on this case, for me the logic answer in that moment was the GET method (to execute the both actions). After this the interviewer asked me why, because since we are also storing the request, this endpoint is not idempotent anymore, after that I wasn't able to reply it. Since this stills on my mind, so I decided to verify here and see others opinions about which method should be used for this case (or how many, GET and POST for example).
You have an REST API where you expose a method to consult the distance between two point, although you must save each request to this method to expose the request history.
How would you do this on the web? You'd probably have a web page with a form, and that form would have input controls to collect the start and end point. When you submit the form, the browser would use the data in the controls, as well as the form metadata and standard HTML processing rules to create a request that would be sent to the server.
Technically, you could use POST as the method of the form. It's completely legal to do that. BUT, as the semantics of the request are "effectively read only", a better choice would be to use GET.
More precisely, this would mean having a family of similar resources, the representation of which includes information about the two points described in the query string.
That family of similar resources would probably be implemented on your origin server as a single operation/route, with a parser extracting the two points from the query string and passing them along to the function as arguments.
the interviewer asked me why, because since we are also storing the request, this endpoint is not idempotent anymore
This is probably the wrong objection - the semantics of GET requests are safe (effectively read only). So the interview might argue that saving the request history is not read only. However, this objection is invalid, because the semantic constraints apply to the request message, not the implementation.
For instance, you may have noticed that HTTP servers commonly add an entry to their access log for each request. Clearly that's not "read only" - but it is merely an implementation detail; the client's request did not say "and also log this".
GET is still fine here, even though the server is writing things down.
One possible objection would be that, if we use GET, then sometimes a cache will return an previous response rather than passing the request all the way through to the origin server to get logged. Which is GREAT - caches are a big part of the reason that the web can be web scale.
But if you don't want caching, the correct way to handle that is to add metadata to the response to inhibit caching, not to change the HTTP method.
Another possibility, which is more consistent with the interviewer's "idempotent" remark, is that they wanted this "request history" to be a resource that the client could edit, and that looking up distances would be a side effect of that editing process.
For instance, we might have some sort of an "itinerary" resource with one or more legs provided by the client. Each time the client modifies the itinerary (for example, by adding another leg), the distance lookup method is called automatically.
In this kind of a problem, where the client is (logically) editing a resource, the requests are no longer "effectively read only". So GET is off the table as an option, and we have to look into the other possibilities.
The TL;DR version is that POST would always be acceptable (and this is how we would do it on the web), but you might prefer an API style where the client edits the representation of the resource locally, in which case you would let the client choose between PUT and PATCH.
what is the best practice in defining web service that represent a non REST command invocation?
For REST, basically we use POST to create new record(s), GET to retrieve record(s), PUT to update record(s) and DELETE to remove record(s). Which http verb should I use if I just want to invoke some other non resource function, for example - to flush a system cache?
Which http verb should I use if I just want to invoke some other non resource function, for example - to flush a system cache?
HTTP request methods should be selected based on their alignment with their defined semantics.
The most important of these is to determine whether or not the semantics are safe
Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server.
Advertising a safe link invites consumers to pre-fetch a link, or to crawl and index the representation found there.
If having Google and a billion of her closest friends flushing your system cache sounds expensive, then you probably don't want a safe method.
PUT and PATCH are unsafe methods with semantics of manipulating representations. So if you had a schema that described a system cache, a client might PUT a representation of an empty cache in the entity body, and send that to you, whereupon you could flush the cache. You could achieve a similar things with PATCH, sending a list of the edits needed to make the change.
Both of these rely on the illusion that your resources are just documents. I GET a representation of your resource, I load that into my generic editor, make changes, send my edited representation back to you, and then it's up to you to manifest those changes (or not).
But they aren't required -- if you want to simply document that
PUT /df1645af-f960-4cc4-ad7a-d0ddd29903f8
Content-Length: 0
has the side effect of flushing the system cache, the REST Police aren't going to come after you just because you've introduced a bit of RPC into the mix.
Of course, if you were doing this with HTML, then your only choice would be POST.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
Which is to say, POST is always an option.
It's easy enough to imagine the flow -- you load up some bookmark, follow a system cache link, find a form with a flush cache button, and submit. The browser would create the request as described in the form elements and submit it.
So that's going to be fine too. And the REST police won't bother you for that, because that protocol is actually RESTful.
If those answers are unsatisfying, or if you are just surveying the space to know what options are available, you can review the HTTP Method Registry. To be honest, I've never found anything there I've wanted to use. But if WebDAV is your jam....
I understand (From the accepted answer What is the difference between HTTP and REST?)
that REST is just a set of rules about how to use HTTP
Accepted answer says:
No, REST is the way HTTP should be used.
Today we only use a tiny bit of the HTTP protocol's methods – namely
GET and POST. The REST way to do it is to use all of the protocol's
methods.
For example, REST dictates the usage of DELETE to erase a document (be
it a file, state, etc.) behind a URI, whereas, with HTTP, you would
misuse a GET or POST query like ...product/?delete_id=22
My question is what is the disadvantage/drawback(technical or design) If I continue to use the POST method instead of DELETE/PUT for deleting/updating the resource in Rest?
My question is what is the disadvantage/drawback(technical or design)
If I continue to use POST method instead of DELETE/PUT for
deleting/updating the resource in Rest ?
The POST request is not Idempotent but the DELETE request is Idempotent.
An idempotent HTTP method is a HTTP method that can be called many times without different outcomes
Idempotency is important in building a fault-tolerant API.
Let's suppose a client wants to update a resource through POST. Since POST is not an idempotent method, calling it multiple times can result in wrong updates. What would happen if you sent out the POST request to the server, but you get a timeout. Did the resource actually get updated? Did the timeout happen when sending the request to the server, or when responding to the client? Can we safely retry again, or do we need to figure out first what happened with the resource? By using idempotent methods, we do not have to answer this question, but we can safely resend the request until we actually get a response back from the server.
So, if you use POST for deleting, there will be consequences.
From a purely technical viewpoint, I am not aware of any real drawbacks. Others mentioned idempotency, but that does not come just by using DELETE, you still have to implement it anyway.
Which leaves us with design considerations:
Your clients (or rather the programmers programming against your API) might reasonably expect the DELETE method to delete things and the POST method to add things. If you don't follow that convention, you confuse them.
If you use POST for both deleting and adding things, you have to invent another way of telling what actually to do. Surely this isn't very hard, but it makes your API more complicated for no good reason.
For both these reasons, you will need more and better documentation, since you're not following RESTful principles, which are already documented.
When we use POST instead of Delete in our rest API then we are snatching power of Idempotency from client.That means,By using POST we are saying to our API user that this API can produce differnent result upon hitting multiple time.
In case of Timeout, API user have to enquiry for the resource
which he had made a request to delete.Then if found,he has to made a
call to POST API to delete it.
Where if same request is made using Delete method.Then we are assuring
our API user that multiple calls to same method will return same
result. Hence he can raise any number of request untill he gets
successful deletion instead of Timeout without enquriy.
Note : Maintaining Idempotency is the duty of API maker.Just putting Delete method do not give Idempotency.
In REST generally we know that POST use to Add something, PUT use to Edit something in existing data and DELETE is use for Delete something and POST request is not Idempotent but the DELETE request is Idempotent.
Although above are definition but in my point of view We are using these methods because for better understanding that particular method is use for what purpose and by using these methods the bridge between UI developer and Backend developer will not be minimized.
if you want to use POST method instead of DELETE/PUT then there will
not any impact but this is not a good coding standard.
I am writing a web-service that perform some software installation in a asynchronous way. In one case a manual action is needed in the middle of the installation. Thus I paused the installation and wait for the user to request the application to resume the installation.
Currently we can retrieve the running installations by performing a GET request on /running-install and cancel a installation with a DELETE on /running-install/<id> but I can't find the appropriate method to use to resume a paused installation.
I was thinking of something like a doing PUT on /running-install/<id> with a body containing {"status":"running"} but it does not feel very right to me.
Thank you
Which HTTP method is the most appropriate to resume an asynchronous task?
Semantically you want to replace the state of a given task with a new state. PUT seems to be a reasonable choice for this scenario.
Quoting the RFC 7231:
4.3.4. PUT
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. [...]
Then send a representation of the new state in the request payload:
PUT /api/installation/1/status HTTP/1.1
Host: example.org
Content-Type: application/json
{ "value" : "running" }
A successful operation could, for example, return 204 and an attempt to modify the status with an invalid state could return 409.
Note: This answer may also be helpful.
If you were implementing this protocol as a sequence of web pages using an html representation, then you would probably use POST here, as you likely don't want clients treating this as a safe interaction.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
Hard to go wrong with that.
Something to keep in mind is that the resources are integration resources.
You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
So if you are having trouble shoehorning the messages you need into the limited resources you have available, then add more resources.
You can make a case for any of POST, PUT, DELETE being correct depending on how you choose to model the integration protocol.
The truth is, if you are actually doing REST, it's perfectly reasonable to offer multiple integration protocols to achieve the same effect. The hypermedia clients can choose which protocol to follow based on the semantics associated with the links on the bookmark page.
I don't see a huge benefit of designing a REST API service that uses PUT and DELETE to update and delete data. These 2 verbs can be easily replaced by using a POST and a unique url.
The only benefit I see of using PUT and DELETE is it cuts down the number of url's that the REST API service uses which isn't much. Are there other benefits that I'm overlooking?
This actually has not so much to do with REST, but more with the Hypertext Transfer Protocol (HTTP).
The basic idea of HTTP is that you perform a certain action (one of the HTTP methods, such as GET, POST, PUT and DELETE) on a certain resource (identified by its URL). So if you start deviating from that by adding the action into the URL (such as http://example.com/api/books/123/delete) and using a different HTTP method, you are violating the HTTP protocol.
The downsides of this might not be instantly visible (because it will still work), and might be limited if you are only using the API by yourself. However, if other programmers are using the API as well, you are creating certain expectations by stating that you have a RESTful HTTP API while you are actually not adhering to the protocol.
For instance, if calling GET /api/books/123 returns a representation of the book resource, a developer expects to be able to call PUT on that same URL to update the information on that book, and DELETE to remove the book alltogether. (of course, if he does not have permissions to do that, you don't actually remove the book but you return a 403 'Forbidden' or 405 'Method Not Allowed' status code - which are also part of the HTTP specification)
However, if you deviate from the protocol (basically inventing your own protocol), you will have to describe somewhere that instead of calling DELETE /api/books/123 developers have to call POST /api/books/123/remove/the/book. They will have to be aware of all your API's custom rules because you are not following the standard.
Another good point is made by Darrel Miller in his answer. The HTTP methods all have a certain meaning and also certain characteristics. For instance, GET is supposed to be a safe method, used to retrieve information without making any changes on the server side. And PUT and DELETE are idempotent, which means that (even though they are not safe methods like GET) you can make as many requests as you like without any unwanted side effects (deleting a book one or ten times has the same effect: the book is gone). POST however is not idempotent: if you do ten POST requests to create a new book, you will most likely end up with 10 duplicate book entries.
Because of these characteristics, developers and tools are able to make certain assumptions. For instance, a search indexer such as Googlebot will only do GET requests, in order to not break anything on the server. However, if you would be violating the HTTP specification by having a URL http://example.com/api/books/123/delete in order to delete a book, you might notice at one day that your database is completely empty because Google has been indexing your site. That wouldn't be Google's fault but yours, because you didn't follow the specification.
So to make a long story short: using a protocol or standard (such as HTTP) sets certain expectations, and if you then deviate from the protocol you will create unexpected behavior and possible unwanted side effects.
It is not required to use PUT and DELETE to get the benefits of a REST based system.
Using the more precise methods can be advantageous in certain cases. Usually it is intermediary components that take advantage of the semantics. PUT and DELETE are idempotent methods, so if some generic component receives a 503, in theory it could retry a PUT/DELETE until it gets a successful response. With a POST method, the intermediary can't do that.
With a DELETE method a client knows not to send a body. With a PUT, it knows to send a complete representation. With a POST method, you need to communicate to the client how to make the request in some other way, like a link relation.
You can live without PUT and DELETE.
This article tells you why: http://www.artima.com/lejava/articles/why_put_and_delete.html
..BUT (quote from Fielding): "A REST API should not contain any changes to the communication protocols aside from filling-out or fixing the details of underspecified bits of standard protocols, such as HTTP’s PATCH method or Link header field. Workarounds for broken implementations (such as those browsers stupid enough to believe that HTML defines HTTP’s method set) should be defined separately, or at least in appendices, with an expectation that the workaround will eventually be obsolete. [Failure here implies that the resource interfaces are object-specific, not generic.] "
(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)