为什么不允许HTTP PUT在REST API中进行部分更新?

Bre*_*den 36 api rest http

谁说RESTful API必须通过HTTP PATCH单独支持部分更新?

它似乎没有任何好处.它增加了在服务器端实现的更多工作,以及客户端的更多逻辑,以决定请求哪种更新.

我在使用HTTP创建REST API的上下文中提出这个问题,该API为已知数据模型提供抽象.需要PATCH进行部分更新而不是PUT的全部或部分感觉它没有任何好处,但我可以被说服.

有关

http://restcookbook.com/HTTP%20Methods/idempotency/ - 这意味着您无法控制可能缓存请求的服务器软件.

不允许部分PUT背后的理由是什么? - 没有明确的答案,只提到HTTP为PUt和PATCH定义的内容.

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/17415 - 显示了对此的分歧.

Ped*_*eck 56

谁说?发明REST的人说:

@mnot Oy,是的,PATCH是我为初始HTTP/1.1提案创建的,因为部分PUT从不RESTful.;-)

https://twitter.com/fielding/status/275471320685367296

首先,REST是一种架构风格,其原则之一是利用其底层协议的标准化行为,因此,如果您想通过HTTP实现RESTful API,则必须严格遵循HTTP以使其成为REST风格.如果你认为它不能满足你的需求,你可以不这样做,没有人会诅咒你,但是你不会做REST.您必须记录偏离标准的位置和方式,在客户端和服务器实现之间创建强大的耦合,使用REST的全部目的正是为了避免这种情况并专注于您的媒体类型.

因此,基于RFC 7231,PUT应仅用于在幂等操作中完全替换表示.PATCH应该用于部分更新,不需要是幂等的,但是通过在应用diff之前要求先决条件或验证当前状态来使它们成为幂等是一件好事.如果您需要进行非幂等更新(部分与否),请使用POST.简单.每个使用API​​的人都知道PUT和PATCH是如何工作的,它们希望它们以这种方式工作,而且您不必记录或解释方法应该对给定资源执行的操作.您可以自由地使PUT以您认为合适的任何其他方式执行,但是您必须为您的客户记录,并且您必须为您的API找到另一个流行语,因为这不是RESTful.

请记住,REST是一种专注于API长期演变的架构风格.要做到这一点,现在就会增加更多的工作,但以后会更容易更改,创伤也更少.这并不意味着REST适用于所有人和每个人.如果您的重点是易于实施和短期使用,只需使用您想要的方法.如果您不想打扰客户选择正确的方法,您可以通过POST完成所有工作.

  • 谢谢您的回答.如果我们同意使用Fielding作为REST的所有东西的来源(注意他承认他不是纯粹主义者并且也做反对REST的事情),他在哪里总结了原则re:PUT/PATCH部分/完全更新?在将PATCH作为RFC提出之前,使用了什么而不是PUT? (2认同)
  • Fielding承认他在REST的上下文之外做了反对REST的事情,这很好,因为REST不适合所有事情.我怀疑他会说在REST架构中对REST做一些事情并且仍然称之为REST是件好事.这些原则在RFC 2616和2068中进行了总结.在PATCH之前,部分更新是通过POST完成的,因为任何未标准化的操作都应该如此.PATCH是一种进行部分更新的标准化方法.您可以通过POST以非标准方式自由地执行此操作,但您必须为您的客户记录它. (2认同)
  • @JonathanW“我想补充一点,对 HTTP 的期望是,当您 PUT 资源时,您应该能够获取相同的资源,并让它看起来与您刚刚 PUT 的完全一样”-不,这是您的*误解* 你总是会得到你刚刚放的东西。你应该明白,绝对不能保证你会得到你刚才放的东西。 (2认同)

The*_*tor 9

为了扩展现有的答案,PUT应该仅仅因为HTTP以这种方式定义方法而执行资源状态的完全更新(覆盖).关于HTTP/1.1原始RFC 2616对此并不十分明确,RFC 7231增加了语义说明:

4.3.4 PUT

PUT方法请求创建目标资源的状态或用请求消息有效负载中包含的表示定义的状态替换目标资源的状态.给定表示的成功PUT将表明在相同目标资源上的后续GET将导致在200(OK)响应中发送等效表示.

如另一个答案所述,遵守此约定简化了API的理解和使用,并且不需要明确记录PUT方法的行为.


但是,由于幂等性,不允许部分更新.我发现这很重要,因为这些概念经常被混淆,甚至在很多StackOverflow答案上(例如这里).

幂等仅意味着一次或多次应用请求会在服务器上产生相同的效果.再次引用RFC 7231:

4.2.2幂等方法

如果使用该方法对服务器的多个相同请求的预期效果与单个此类请求的效果相同,则请求方法被视为"幂等".

只要部分更新仅包含资源状态的新值并且不依赖于先前的值(即,那些值被覆盖),就满足了幂等性的要求.与应用此类部分更新的次数无关,服务器的状态将始终保持请求中指定的值.

来自另一个客户端的中间请求是否可以改变资源的不同部分是不相关的,因为幂等性指的是操作(即PUT方法),而不是状态本身.并且对于部分重写更新的操作,其应用在应用一次或多次之后产生相同的效果.

相反,非幂等的操作取决于当前服务器状态,因此根据执行的次数导致不同的结果.最简单的例子是递增一个数字(非幂等),而不是将其设置为绝对值(幂等).

对于非幂等的变化,HTTP预见方法POSTPATCH,而PATCH被明确设计成承载修改一个现有的资源,而POST可以更加自由地被解释关于请求URI,主体内容和在服务器上的副作用的关系.


这在实践中意味着什么?REST是通过HTTP协议实现API的范例 - 许多人认为这种惯例是合理的,因此很可能被采用或理解.仍然存在关于什么是RESTful和什么不存在的争议,但即使不考虑这些,REST也不是构建HTTP API的唯一正确或有意义的方式.

HTTP协议本身会限制您可能会做什么,也可能不会做什么,并且其中许多都具有实际的实际影响.例如,忽略幂等性可能导致缓存服务器改变客户端实际发出的请求数,并随后破坏应用程序所期望的逻辑.因此,在偏离标准时要注意其含义至关重要.

严格遵守REST,没有完全令人满意的部分更新解决方案(有些人甚至说这需要单独使用REST).问题是PATCH,首先看来只是为了这个目的而制造的,并不是幂等的.因此,通过使用PATCH幂等部分更新,您将失去幂等性的优势(任意数量的自动重试,更简单的逻辑,可能在客户端,服务器和网络中进行优化).因此,您可能会问自己,使用PUT是否真的是最糟糕的想法,只要行为明确记录并且不会因为用户(和中间网络节点)依赖某些行为而中断......?