11

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

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

编辑:

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

4

3 回答 3

8

您正确地指出,HTTP 协议中没有任何内在的东西可以强制方法/动词(如PUT和)的幂等属性DELETE。HTTP 是一种无状态协议,不保留用户发出的每个请求的信息或状态;每个请求都被视为独立的。

引用维基百科关于HTTP 方法的幂等属性(强调我的):

请注意,协议或 Web 服务器不强制执行方法是否具有幂等性。完全可以编写一个 Web 应用程序,其中(例如)数据库插入或其他非幂等操作由 GET 或其他请求触发。但是,如果用户代理认为重复相同的请求是安全的,而实际上并非如此,那么忽略此建议可能会导致不良后果。

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

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

实施者应该意识到该软件代表了用户在互联网上的交互,并且应该小心让用户意识到他们可能采取的任何可能对他们自己或他人产生意想不到的意义的行动。

特别是,已经建立了约定,即 GET 和 HEAD 方法不应该具有采取除检索之外的操作的意义。这些方法应该被认为是“安全的”。这允许用户代理以特殊的方式表示其他方法,例如 POST、PUT 和 DELETE,以便用户意识到正在请求可能不安全的操作。

当然,不可能确保服务器不会因为执行 GET 请求而产生副作用;事实上,一些动态资源认为这是一个特性。这里的重要区别是用户没有请求副作用,因此不能对它们负责。

更新:正如Julian所指出的,RFC 2616 已被 RFC 7231 取代。这是相应的部分

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

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

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

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

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

相反,作为 POST Web 服务的消费者,我会期望这样的请求:

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

更新相应的现有用户,而请求如下所示:

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

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

于 2015-01-01T07:19:04.420 回答
2

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

于 2015-01-01T10:32:28.057 回答
2

希望链接对您有所帮助:HTTP Method idempotency

在处理安全方法时也要小心:如果像 GET 这样看似安全的方法会更改资源,则您和服务器之间的任何中间件客户端代理系统都可能会缓存此响应。另一个客户端想要通过相同的 URL(如:http ://example.org/api/article/1234/delete )更改此资源,不会调用服务器,而是直接从缓存中返回信息。任何中间件代理都不会缓存非安全(和非幂等)方法。

于 2015-01-01T20:02:49.220 回答