Context
I have a REST API where multiple clients (applications) can update the state of a resource with PUT. For the example, this resource is a lamp that you can turn ON
or OFF
.
This resource is also automatically updated by the system when it detects that an electricity failure has occurs, leading to have a lamp in a BROKEN
state. I want to made the distinction between BROKEN
and OFF
, a lamp in BROKEN
can not be turn ON
!
Problem
I use PUT
method to do this, something like PUT http://address:port/my_lamp { "state": "ON"}
But I am not sure if i respect the idempotent property of PUT
method.
In fact, i have 3 cases:
- The lamp is
ON
. The above code leads to theON
state. - The lamp is
ON
. The above code leads to theON
state.... cool! At this moment, idempotency is still guaranteed :-) ! - The lamp is
BROKEN
. The above code leads to an error, like503 Service Unavailable
Question
I am not sure to correctly understand the notion of idempotency. Trust me, I read a lot of thing about it but still a little bit confused.
In my understanding, multiple PUT
always leads to a same state of the resource: not guaranteed in my case due to BROKEN
But I could also understand it in an other way: multiple PUT
always leads to the same side-effect: guaranteed, my request either produce to turn ON
, either nothing (for the BROKEN
case, it was already in).
EDIT:
I mean: the only side-effect is to turnON
the lamp, which is guaranteed (it either turn-on or do nothing here)
See here: Is REST DELETE really idempotent?
Which one is correct ? Depending of the understanding, my REST API ensure idempotency or not...
EDIT2:
From the definition of the W3CMethods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.
Can i consider that it's an error to turn ON
the lamp when it is BROKEN
?
Idempotency means that in an isolated environment multiple requests from a same client does not have any effect on the state of resource. If request from another client changes the state of the resource, than it does not break the idempotency principle. Although, if you really want to ensure that put request does not end up overriding the changes by another simultaneous request from different client, you should always use etags. To elaborate, put request should always supply an etag (it got from get request) of the last resource state, and only if the etag is latest the resource should be updated, otherwise 412 (Precondition Failed) status code should be raised. In case of 412, client is suppose to get the resource again, and then try the update. According to REST, this is vital to prevent race conditions.
To elaborate even more:-
According to W3C(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html), 'Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.'
Get request - {'state': 'ON'} Etag-header(say)- 123 PUT request - {'state': 'OFF'} Etag-header - 123
Some internal activity changes state such that new state is {'state': 'BROKEN'}. In this even etag should be changed to say 124.
put request - {'state': 'ON'} Etag-header - 123. Since etag header has changed, 412 error is returned which does not break idempotence of api (aside from error or expiration issues).
Get request - {'state': 'BROKEN'} Etag-header - 124 Put request - {'state': 'ON'} Etag-header - 124