为了扩展现有的答案,PUT
应该执行资源状态的完整更新(覆盖),因为 HTTP 以这种方式定义了方法。关于 HTTP/1.1的原始 RFC 2616 对此不是很明确,RFC 7231增加了语义说明:
4.3.4 放置
PUT 方法请求创建目标资源的状态或将其替换为请求消息有效负载中包含的表示定义的状态。给定表示的成功 PUT 将表明对同一目标资源的后续 GET 将导致在 200(OK)响应中发送等效表示。
如另一个答案所述,遵守此约定可以简化对 API 的理解和使用,无需显式记录 PUT 方法的行为。
但是,部分更新不会因为幂等性而被禁止。我发现这一点很重要,因为这些概念经常被混淆,即使在许多 StackOverflow 答案中(例如这里)。
幂等仅意味着应用请求一次或多次会在服务器上产生相同的效果。再次引用 RFC 7231:
4.2.2 幂等方法
如果使用该方法的多个相同请求对服务器的预期效果与单个此类请求的效果相同,则该请求方法被认为是“幂等的”。
只要部分更新只包含资源状态的新值并且不依赖于先前的值(即那些值被覆盖),就满足了幂等性的要求。与应用这种部分更新的次数无关,服务器的状态将始终保持请求中指定的值。
来自另一个客户端的中间请求是否可以更改资源的不同部分无关紧要,因为幂等性指的是操作(即PUT
方法),而不是状态本身。并且对于部分覆盖更新的操作,它的应用在应用一次或多次后产生相同的效果。
相反,一个非幂等的操作取决于当前的服务器状态,因此它会根据执行的次数而导致不同的结果。最简单的例子是增加一个数字(非幂等)与将其设置为绝对值(幂等)。
对于非幂等的更改,HTTP 预见了方法POST
和PATCH
,而 ,PATCH
被明确设计为对现有资源进行修改,而POST
可以更自由地解释请求 URI、正文内容和服务器上的副作用的关系。
这在实践中意味着什么?REST 是通过 HTTP 协议实现 API 的范例——许多人认为这种约定是合理的,因此很可能被采用或理解。尽管如此,关于什么是 RESTful 什么不是,仍然存在争议,但即使抛开这些,REST 也不是构建 HTTP API 的唯一正确或有意义的方式。
HTTP 协议本身对您可以做什么和不可以做什么施加了限制,其中许多具有实际的实际影响。例如,忽略幂等性可能会导致缓存服务器更改客户端实际发出的请求数量,从而破坏应用程序预期的逻辑。因此,了解偏离标准时的影响至关重要。
由于严格符合 REST,对于部分更新没有完全令人满意的解决方案(有些人甚至说这种需求本身就是反对 REST)。问题在于PATCH
,最初似乎只是为了这个目的而制作的,它不是幂等的。因此,通过使用PATCH
幂等部分更新,您将失去幂等性的优势(任意次数的自动重试、更简单的逻辑、优化客户端、服务器和网络的潜力)。因此,您可能会问自己,使用PUT
是否真的是最糟糕的主意,只要行为被清楚记录并且不会因为用户(和中间网络节点)依赖某些行为而中断......?