For understanding idempotency in REST, your best starting point is probably going to be the definition include in RFC 7231
A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
For "effect", think side effect. When the server is advertising that a particular action is idempotent, it is telling you that the (semantically significant) side effects will happen at most once.
// the guarantee of an idempotent operation
oldState.andThen(PUT(newState)) === oldState.andThen(PUT(newState)).andThen(PUT(newState))
Safe methods are inherently idempotent, because they have no effect on the server.
// the guarantee of a safe operation
oldState === oldState.andThen(GET)
// therefore, the guarantee of an idempotent operation follows trivially
oldState.andThen(GET) == oldState.andThen(GET).andThen(GET)
So does idempotency actually has something to do with server-work or a response?
Server work. More generally, its a constraint on the receiver of a command to change state.
Roy Fielding shared this observation in 2002:
HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).
If you substitute PUT/DELETE for GET, and idempotent for safe, I think you get a good picture -- if a loss of property occurs because the server received two copies of an idempotent request, the fault is that the server handled the request improperly, not that the client broadcast the request more than once.
This is important because it allows for at least once delivery over an unreliable network. From RFC 7231
Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response.
Contrast this with POST; which does not promise idempotent handling. Submitting a web form twice may produce two side effects on the server, so the client implementations (and intermediary components, like proxies) cannot assume it is safe to repeat a lost request.
Back in the day, dialogs like this were common
for precisely this reason
And finally, is idempotency same server-work over and over again, or same results over and over again for the same/single request?
Work on the server. An idempotent change is analogous to SET, or REPLACE (aka, compare and swap).
The responses may, of course, be different. A conditional PUT, for example, will include meta data "indicating a precondition to be tested before applying the method semantics to the target resource."
So the server might change state in response to the receiving the first copy of a put, sending back 200 OK
to indicate to the client that the request was successful; but upon receiving the second request, the server will find that the now-changed state of the resource no longer matches the provided meta data, and will respond with 412 Precondition Failed
.
I noticed you mentioned may produce in "Contrast this with POST; which does not promise idempotent handling. Submitting a web form twice may produce two side effects on the server....." basically rest standards declare POST as non-idempotent, but one could actually make POST an idempotent, but it would be opposite to rest standards...
No, that's not quite right. The HTTP specification does not require that POST support idempotent semantics -- which means that clients and intermediaries are not permitted to assume that it does. The server controls its own implementation; it may provide idempotent handling of the POST request.
But the server has no way to advertise this capability to the clients (or intermediaries), so that they can take advantage of it.