50

谁说 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 - 显示了对此的看法分歧。

4

3 回答 3

76

谁说?发明 REST 的人说:

@mnot Oy,是的,PATCH 是我为最初的 HTTP/1.1 提案创建的东西,因为部分 PUT 绝不是 RESTful。;-)

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

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

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

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

于 2013-11-01T22:42:32.043 回答
16

为了扩展现有的答案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 预见了方法POSTPATCH,而 ,PATCH被明确设计为对现有资源进行修改,而POST可以更自由地解释请求 URI、正文内容和服务器上的副作用的关系。


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

HTTP 协议本身对您可以做什么和不可以做什么施加了限制,其中许多具有实际的实际影响。例如,忽略幂等性可能会导致缓存服务器更改客户端实际发出的请求数量,从而破坏应用程序预期的逻辑。因此,了解偏离标准时的影响至关重要。

由于严格符合 REST,对于部分更新没有完全令人满意的解决方案(有些人甚至说这种需求本身就是反对 REST)。问题在于PATCH,最初似乎只是为了这个目的而制作的,它不是幂等的。因此,通过使用PATCH幂等部分更新,您将失去幂等性的优势(任意次数的自动重试、更简单的逻辑、优化客户端、服务器和网络的潜力)。因此,您可能会问自己,使用PUT是否真的是最糟糕的主意,只要行为被清楚记录并且不会因为用户(和中间网络节点)依赖某些行为而中断......?

于 2016-12-19T22:33:39.480 回答
-4

PUT 允许部分更新(根据 RFC 7231 https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4)。

",... PUT 请求被定义为替换目标资源的状态。" - 替换部分对象基本上会改变它的状态。

“通过针对具有与较大资源的一部分重叠的状态的单独标识的资源,可以进行部分内容更新......”

根据该 RFC 下一个请求是有效的:PUT /resource/123 {name: 'new name'} 它只会更改指定资源的名称。在请求负载中指定 id 是不正确的(因为 PUT 不允许对未指定的资源进行部分更新)。

PS:下面是 PATCH 有用的例子。

有一个里面有数组的对象。使用 PUT,您无法更新特定值。您只能将整个列表替换为新列表。使用 PATCH,您可以将一个值替换为另一个值。有了地图和更复杂的对象,好处会更大。

于 2014-08-22T08:12:26.010 回答