PUT POST 是幂等的 (REST)

PUT POST being idempotent (REST)

我不太明白 HTTP 动词是如何定义为幂等的。我只读过 GET 和 PUT 是幂等的。 POST 不是幂等的。但是您可以使用 POST 创建一个 REST API,它不会改变任何东西(例如在数据库中),或者为 PUT 创建一个 REST API,每次调用时都会改变。

当然,这可能是错误的做事方式,但如果可以做到,为什么在实施时将 PUT 标记为幂等(或 POST 不是)?我不是在挑战这个想法,我可能遗漏了一些东西,我要求澄清我的理解。

我想提出我的问题的一种方式是:如果我使用 PUT 进行非幂等调用并且 POST 这样做会出现什么问题?

您指出 HTTP 协议中并没有像 PUTDELETE 那样强制执行 methods/verbs 的幂等属性的固有内容是正确的。 HTTP,作为 stateless protocol,不保留用户发出的每个请求的信息或状态;每个请求都被视为独立的。

idempotent attribute of HTTP methods 上引用维基百科(强调我的):

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.

所以是的,有可能偏离传统的实施方式,推出诸如不变 POST 实施、非幂等 PUT 等可能没有重大的、危及生命的技术问题。但是您可能会冒着让其他使用您的 Web 服务的程序员不高兴的风险,认为您不知道自己在做什么。

这是来自 RFC2616 的关于 HTTP 方法 安全 的重要引述(强调我的):

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.

更新:正如Julian, RFC 2616 has been replaced by RFC 7231. Here's the corresponding section所指出的那样。

因此,当您将 Web 服务发布为 PUT 方法时,我提交的请求如下所示:

PUT /users/<new_id> HTTP/1.1
Host: example.com

我希望创建一个新的用户资源。同样,如果我的请求如下所示:

PUT /users/<existing_id> HTTP/1.1
Host: example.com

我希望相应的现有用户得到更新。如果我通过多次提交表单来重复相同的请求,请不要弹出警告对话框(因为我喜欢既定的约定)。

相反,作为 POST 网络服务的消费者,我会收到如下请求:

POST /users/<existing_id> HTTP/1.1
Host: example.com

更新相应的现有用户,同时发出如下请求:

POST /users/<new_id> HTTP/1.1
Host: example.com

引发错误,因为 URL 尚不存在。

确实,一个实现可以做任何它想做的事情。但是,如果根据协议规范这是不正确的,则可能会发生令人惊讶的事情(例如,如果第一次尝试失败,库或中介会重复 PUT)。

希望link对您有所帮助: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.