What is idempotency in HTTP PUT? Can I disallow overwriting of a resource?

What is idempotency in HTTP PUT? Can I disallow overwriting of a resource?



I'm writing a REST API and I wish to allow authenticated users with the proper permissions to upload files via this API. I thought I'd use a PUT endpoint to handle this. I want to include a failsafe where the request will be rejected with a 400-family error if the resource already exists and the user did not specify via a query that the resource should be overwritten (i.e. PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1).


PUT


400


PUT https://my.server.com/api/files/path/to/file.txt?overwrite=1



The HTTP/1.1 RFC documentation of PUT suggests that such a scenario is allowed:



If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem.



But I'm hung up on the concept of idempotency. The spec says:



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. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.



However, it is possible that a sequence of several requests is non- idempotent, even if all of the methods executed in that sequence are idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that is not changed by a reexecution of all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence.



A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).



I can't wrap my head around this as it applies to my scenario. If PUT https://my.server.com/myfile.txt returns a 201 Created the first time it's run, then a 403 Forbidden or 409 Conflict error without doing anything else on a subsequent request simply because the file already exists, does that violate the concept of idempotency? Does having to tack a query onto the URI to bypass the failsafe violate idempotency?


PUT https://my.server.com/myfile.txt


201 Created


403 Forbidden


409 Conflict




1 Answer
1



This is a common thinking mistake with idempotency.



The point of the rule is NOT that multiple identical requests get the same response.



The point of the rule is that if you send the same request multiple times, the state of the server is the same as if you only sent it once.



So if you send the same request twice, the second will error and get ignored, but the state on the server is still the same as if you only sent the first.



The updated HTTP standard has an interesting note though:



An origin server MUST NOT perform the requested method if a received
If-Match condition evaluates to false; instead, the origin server
MUST respond with either a) the 412 (Precondition Failed) status code
or b) one of the 2xx (Successful) status codes if the origin server
has verified that a state change is being requested and the final
state is already reflected in the current state of the target
resource (i.e., the change requested by the user agent has already
succeeded, but the user agent might not be aware of it, perhaps
because the prior response was lost or a compatible change was made
by some other user agent). In the latter case, the origin server
MUST NOT send a validator header field in the response unless it can
verify that the request is a duplicate of an immediately prior change
made by the same user agent.



Even though that paragraph is specific to using the If-Match header, it might apply here too. Maybe you want to just return 201 Created if you can detect that the exact same request was sent. That's kind of off-topic to your question though.


If-Match


201 Created



As an aside, you should use conditional headers instead of ?overwrite=1. If you explicitly don't want to allow a client to update a resource if it has been created, the client can simply include:


?overwrite=1


If-None-Match: *



Then your server can return 412 Precondition Failed, signaling the client that the resource was created earlier. Furthermore, if you want to force a client to always include this header, you can use 428 Precondition Required to tell a client.


412 Precondition Failed


428 Precondition Required





I've seen mention of server "state" before along these lines and it's served only to muddy my understanding further. What exactly is meant by "state" in the context of idempotency?
– p0lar_bear
Aug 21 at 17:45





As an example, if you are building an API with a MySQL database, the 'state' would be the fact that a new record was created in mysql. It will get created on the first request, not the second.
– Evert
Aug 21 at 17:47





@p0lar_bear added a ton of more background, hope it helps.
– Evert
Aug 21 at 17:49





Oh! Alright, I get it now - it's not a matter of whether the response is the same, it's a matter of whether the data stored on the server has changed. Moreover, I had narrowed my scope of what constitutes a request too much, and forgot that the request body (i.e. the uploaded file) is a part of it - uploading the same exact file twice should have no impact on the data stored on the server.
– p0lar_bear
Aug 26 at 0:46






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

ャフサォクコ ケウ,コ,ワ メ,ロスョノ゙,クネ,フムカヤヲニ,エコ゚ツ ウイオン゙ケワサネォキモュキォウイノンコチ゚メヌナイゥフュ,カヒウネェ ネ,ホノケ,ムュキ ッボーミュハ,チ ツス ィ メウイマヤ,゙ウチ ヅ ロ,ォジヌェ ャヌット ェ,マャ,チナエヒネソキツテ トホヲヲミーァ

How do I collapse sections of code in Visual Studio Code for Windows?