资源的 Http 幂等部分修改更好地实现为 PUT 而不是 PATCH?

Http idempotent partial modifications of a resource are better of implemented as PUT instead of PATCH?

Http PATCH 方法被认为是非幂等的并且对资源应用部分修改,

与 PUT 相反,PUT 是幂等的并应用资源替换。

(如 MDN 所述):

The HTTP PATCH request method applies partial modifications to a resource.

The HTTP PUT method only allows complete replacement of a document. Unlike PUT, PATCH is not idempotent, meaning successive identical patch requests may have different effects.

但是可以以幂等的方式实现PATCH (MDN) :

However, it is possible to issue PATCH requests in such a way as to be idempotent.

补丁的幂等实现示例是:

path: /contact/:id
method: patch
body {
name: 'John'
}

无论发出多少次此请求 - 资源将保持与第一次请求后相同的状态。

自幂等请求得到优化 (reference):

Clients may automatically cancel a GET request if it is taking too long to process and repeat it because they assume it has the same effect (since GET is idempotent). However, they won’t do the same thing for POST requests because the first one may have already altered some state on the server side.

据我了解,此优化只能应用于 HTTP 标准认为是幂等的 http 方法。

因此我上面写的幂等PATCH请求不会被优化。 (据我所知,HTTP 标准规定补丁是非幂等的——但并不禁止它作为幂等实现)。

因为 HTTP 标准认为 PUT 是幂等的。 不是更喜欢使用 /contact/:id PATCH 请求作为 PUT(以获得上述优化)吗?

更新 1


我可以将请求修改为 PUT 并在服务器中以仅更新请求有效负载中发送的属性的方式实现它,而忽略未发送的属性。 通过这种方式,我正在执行 PUT 请求,该请求以将被优化的幂等方式修改部分资源,并且我不会替换整个资源。 如果资源非常大而我想做的更改非常小,如果它以幂等方式实现,每次都使用 PUT 不是更好吗?

这让我想到了标题: 资源的幂等部分修改最好用 PUT 而不是 PATCH 来实现?


更新 2:


正如这个 question 答案中所述: 1 , 2

HTTP 幂等部分修改没有像 PUT 那样更好地实现的原因是:它违背了 REST 架构设计

随之而来的一些缺点是:

  1. 其他程序员不会理解部分更新 PUT ,应该编写有关该端点的进一步文档。

  2. 将无法获取在之前 "partial updating PUT" 中发送的确切资源。

  3. 由于 REST 专注于我们 API 的长期发展,坚持 它可能会在未来为我们节省时间。

不遵守 REST 架构风格可能还有很多缺点...

但如果我们从性能的角度来看,如果请求是幂等的,则部分 PUT 更新会更好(因为它得到了上述优化)。

我很乐意听到更多想到的原因 :) 。

谢谢

as i understand HTTP standard states that patch is non idempotent - but does not forbid it to be implemented as idempotent

没错。更准确地说,该标准不保证幂等语义。

idempotent partial modifications of a resource are better of implemented as PUT instead of PATCH ?

“视情况而定”。

是的,你是对的,如果使用 PUT,那么通用组件将能够识别服务器承诺对请求进行幂等处理,因此自动重新发送消息是安全的(例如,如果我们等待响应到达超时)。

PATCH 不会有同样的行为,因为中间人需要了解补丁文档的媒体类型,并深入挖掘请求有效负载,试图弄清楚发生了什么。

但是...没有“部分 PUT”这样的东西。如果所需的资源表示非常大,而您想要进行的更改非常小,那么发送补丁文档而不是完整的表示会很有意义。

选择归结为权衡顾虑 - 您遇到的哪些问题最重要,哪些可以忽略。

why there is not such thing a partial PUT ?

因为 HTTP 语义没有那样定义它。 RFC 7231

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload. A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.

PUT 并不意味着“对此请求应用幂等处理”。意思是替换;类似于覆盖文件系统或变量集上的文件的东西。

请记住,统一接口 是 REST 约束之一 - 它允许我们使用 generic 组件进行通信标准方式。

如果您想要幂等的部分替换,遵守 REST 约束,那么您要做的就是为新方法创建规范。有一个定义明确的 process, and a registry,您可以在其中查找已通过流程的方法的标准。

定义方法后,组件提供商可以决定是否选择加入并支持您的新标准。

换句话说:在您控制客户端和服务器的情况下,将自定义语义嵌入到消息中并没有错。但是,如果您打算使用一种标准方法类型来执行此操作,那么您应该使用 POST——因为这是通用组件对正在发生的事情做出最少假设的方法。