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

丶灬走出姿态 提交于 2019-12-08 12:13:38

问题


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

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?


回答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.

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:

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.




回答2:


Below API standards apply, I use them a lot when making references to 'agreed standards'.

All credit goes to : https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md Below is a list of methods that Microsoft REST services SHOULD support. Not all resources will support all methods, but all resources using the methods below MUST conform to their usage.



来源:https://stackoverflow.com/questions/51953943/what-is-idempotency-in-http-put-can-i-disallow-overwriting-of-a-resource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!