PUT POST being idempotent (REST)
Asked Answered
B

3

11

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?

Beadle answered 1/1, 2015 at 3:54 Comment(5)
An implementation can do whatever it wants, yes, but then it might be considered noncompliant with the standard.Venosity
stormpath.com/blog/put-or-post hope the link above helps..Mostly
@icktoofay: In that case, what would be the implications if I use PUT for POST and vice-versa?Beadle
@ManinGreen: Thanks for the great link. The article mentioned that you can also implement a non-changing POST implementation. That is what is not clear with me. What would be the problem is I used PUT to make a non-idempotent call?Beadle
@Beadle Totally agree with this question, is like the way people say that PUT is idempotent would mean like it is idempotent by itself, when it isn't at all.Coniferous
L
8

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.

Lahdidah answered 1/1, 2015 at 7:19 Comment(3)
@JulianReschke Thanks for the info. I have updated my answer to point out that RFC 2616 is obsolete. Though the quote I used no longer appears in RFC 7231, don't you think it still applies? Thanks.Lahdidah
@Lahdidah Your example for POST needs to be swapped and questions is to be replaced with usersDiphyllous
@Lahdidah How you can find out existing_id, or generate new_id, for stateless http, where to store existing id? ok can you explain real use of UUID or GUID ?Kwon
S
2

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).

Subtract answered 1/1, 2015 at 10:32 Comment(0)
O
2

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.

Opiumism answered 1/1, 2015 at 20:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.