在 REST API 现实生活场景中使用 PUT 与 PATCH 方法

Use of PUT vs PATCH methods in REST API real life scenarios

首先是一些定义:

PUT 在 Section 9.6 RFC 2616:

中定义

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

补丁定义在RFC 5789:

The PATCH method requests that a set of changes described in the request entity be applied to the resource identified by the Request- URI.

另外根据 RFC 2616 Section 9.1.2 PUT 是幂等的而 PATCH 不是。

现在让我们来看一个真实的例子。当我使用数据 {username: 'skwee357', email: 'skwee357@domain.com'} 执行 POST 到 /users 并且服务器能够创建资源时,它将响应 201 和资源位置(让我们假设 /users/1)和下一次调用 GET /users/1 将 return {id: 1, username: 'skwee357', email: 'skwee357@domain.com'}.

现在假设我想修改我的电子邮件。电子邮件修改被认为是“一组更改”,因此我应该用“patch document”修补 /users/1。在我的例子中,它将是 json 文档:{email: 'skwee357@newdomain.com'}。然后服务器 returns 200(假设权限没问题)。这让我想到第一个问题:

PATCH是一个比较新的动词(RFC在2010年3月引入),它来解决“打补丁”或修改一组字段的问题。在引入 PATCH 之前,大家都使用 PUT 来更新资源。但是引入PATCH之后,让我很困惑PUT是干什么用的。这让我想到了第二个(也是主要的)问题:

我对此也很好奇,发现了一些有趣的文章。我可能无法全面回答您的问题,但这至少提供了一些信息。

http://restful-api-design.readthedocs.org/en/latest/methods.html

The HTTP RFC specifies that PUT must take a full new resource representation as the request entity. This means that if for example only certain attributes are provided, those should be remove (i.e. set to null).

鉴于此,PUT 应该发送整个对象。例如,

/users/1
PUT {id: 1, username: 'skwee357', email: 'newemail@domain.com'}

这将有效地更新电子邮件。 PUT 可能不太有效的原因是您真正修改一个字段并包括用户名有点无用。下一个示例显示了差异。

/users/1
PUT {id: 1, email: 'newemail@domain.com'}

现在,如果 PUT 是根据规范设计的,那么 PUT 会将用户名设置为 null,您将得到以下内容。

{id: 1, username: null, email: 'newemail@domain.com'}

当您使用 PATCH 时,您只更新您指定的字段,其余部分如您的示例所示。

以下对 PATCH 的看法与我以前从未见过的略有不同。

http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/

The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.

PATCH /users/123

[
    { "op": "replace", "path": "/email", "value": "new.email@example.org" }
]

您或多或少将 PATCH 视为更新字段的一种方式。因此,您不是发送部分对象,而是发送操作。即用值替换电子邮件。

文章到此结束

It is worth mentioning that PATCH is not really designed for truly REST APIs, as Fielding's dissertation does not define any way to partially modify resources. But, Roy Fielding himself said that PATCH was something [he] created for the initial HTTP/1.1 proposal because partial PUT is never RESTful. Sure you are not transferring a complete representation, but REST does not require representations to be complete anyway.

现在,我不知道我是否像许多评论员指出的那样特别同意这篇文章。发送部分表示很容易成为对更改的描述。

对我来说,我对使用 PATCH 的态度喜忧参半。在大多数情况下,我会将 PUT 视为 PATCH,因为到目前为止我注意到的唯一真正区别是 PUT "should" 将缺失值设置为 null。这可能不是 'most correct' 的方法,但祝你编码完美。

注意:当我第一次花时间阅读有关 REST 的内容时,幂等性是一个难以理解的概念。正如进一步的评论(和 )所示,我在最初的回答中仍然没有完全正确。有一段时间,我一直拒绝广泛更新这个答案,以避免有效地剽窃 Jason,但我现在正在编辑它,因为,好吧,我被要求(在评论中)。

看完我的回答后,我建议你也阅读这个问题,我会尽量让我的回答更好,而不是简单地从杰森那里窃取。

为什么 PUT 是幂等的?

正如您在 RFC 2616 引文中指出的那样,PUT 被认为是幂等的。当您 PUT 资源时,这两个假设在起作用:

  1. 您指的是一个实体,而不是一个集合。

  2. 您提供的实体已完成(整个实体)。

让我们看看你的例子之一。

{ "username": "skwee357", "email": "skwee357@domain.com" }

如果按照您的建议POST将此文档/users,那么您可能会取回一个实体,例如

## /users/1

{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}

如果以后要修改此实体,请在 PUT 和 PATCH 之间进行选择。 PUT 可能如下所示:

PUT /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // new email address
}

您可以使用 PATCH 完成相同的操作。这可能看起来像这样:

PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

您会立即注意到这两者之间的区别。 PUT 包含此用户的所有参数,但 PATCH 仅包含正在修改的参数 (email)。

使用 PUT 时,假设您要发送完整的实体,并且完整的实体 替换 该 URI 上的任何现有实体。在上面的示例中,PUT 和 PATCH 实现了相同的目标:它们都更改了该用户的电子邮件地址。但是 PUT 通过替换整个实体来处理它,而 PATCH 只更新提供的字段,而不会影响其他字段。

由于 PUT 请求包括整个实体,如果您重复发出相同的请求,它应该总是有相同的结果(您发送的数据现在是实体的全部数据)。因此 PUT 是幂等的。

使用 PUT 错误

如果在 PUT 请求中使用上述 PATCH 数据会怎样?

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}
PUT /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "email": "skwee357@gmail.com"      // new email address... and nothing else!
}

(出于这个问题的目的,我假设服务器没有任何特定的必填字段,并且会允许这种情况发生......实际情况可能并非如此。)

由于我们使用了 PUT,但只提供了 email,现在这是该实体中唯一的东西。这导致数据丢失。

此示例仅供说明之用——切勿实际执行此操作。这个 PUT 请求在技术上是幂等的,但这并不意味着它不是一个糟糕的、失败的想法。

PATCH如何做到幂等?

在上面的例子中,PATCH 幂等的。您进行了更改,但如果您一次又一次地进行相同的更改,它总是返回相同的结果:您将电子邮件地址更改为新值。

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.com"
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // email address was changed
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address... again
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // nothing changed since last GET
}

我的原始示例,已修复以确保准确性

我最初有我认为显示非幂等性的例子,但它们具有误导性/不正确。我将保留示例,但用它们来说明不同的事情:针对同一实体的多个 PATCH 文档,修改不同的属性,不会使 PATCH 非幂等。

假设在过去的某个时间添加了一个用户。这是您开始的状态。

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.com",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

PATCH 之后,您有一个修改后的实体:

PATCH /users/1
{"email": "skwee357@newdomain.com"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",    // the email changed, yay!
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

如果您随后重复应用 PATCH,您将继续得到相同的结果:电子邮件已更改为新值。 A进去,A出来,所以这是幂等的。

一个小时后,在你去泡咖啡休息之后,其他人带着他们自己的 PATCH 来了。看来 Post 办公室一直在做一些改变。

PATCH /users/1
{"zip": "12345"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",  // still the new email you set
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"                      // and this change as well
}

由于post办公室的这个PATCH不关心邮箱,只关心邮政编码,如果重复应用,也会得到相同的结果:邮政编码设置为新的价值。 A 进去,A 出来,所以这是 幂等。

第二天,您决定再次发送 PATCH。

PATCH /users/1
{"email": "skwee357@newdomain.com"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.com",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"
}

您的补丁与昨天的效果相同:它设置了电子邮件地址。 A进去,A出来,所以也是幂等的。

我原来的回答错了什么

我想做一个重要的区分(我在原来的回答中弄错了)。许多服务器将通过发回新的实体状态以及您的修改(如果有)来响应您的 REST 请求。因此,当您收到此 回复 时,它与您昨天收到的 不同 ,因为邮政编码不是您收到的那个上次。但是,您的请求与邮政编码无关,只与电子邮件有关。所以你的 PATCH 文档仍然是幂等的——你在 PATCH 中发送的电子邮件现在是实体上的电子邮件地址。

那么PATCH什么时候不是幂等的呢?

关于这个问题的完整处理,我再次推荐你参考 。我就此打住,因为老实说,我认为我无法比他已经回答得更好。

虽然 Dan Lowe 的出色回答非常彻底地回答了 OP 关于 PUT 和 PATCH 之间的区别的问题,但它对为什么 PATCH 不是幂等的问题的回答不太正确。

为了说明为什么 PATCH 不是幂等的,它有助于从幂等的定义开始(来自 Wikipedia):

The term idempotent is used more comprehensively to describe an operation that will produce the same results if executed once or multiple times [...] An idempotent function is one that has the property f(f(x)) = f(x) for any value x.

用更易于理解的语言,幂等 PATCH 可以定义为:在使用补丁文档对资源进行 PATCH 之后,所有后续使用相同补丁文档对同一资源的 PATCH 调用都不会更改该资源。

相反,非幂等操作是其中 f(f(x)) != f(x),对于 PATCH 可以表述为:在使用补丁文档对资源进行 PATCH 之后,随后的 PATCH 调用同一个资源同一个补丁文档do改变资源

为了说明非幂等 PATCH,假设有一个 /users 资源,并假设调用 GET /users returns 用户列表,当前:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" }]

而不是 PATCHing /users/{id},就像在 OP 的例子中那样,假设服务器允许 PATCHing /users。让我们发出这个 PATCH 请求:

PATCH /users
[{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]

我们的补丁文档指示服务器将名为 newuser 的新用户添加到用户列表中。第一次调用后,GET /users 会 return:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" }]

现在,如果我们像上面那样发出 完全相同的 PATCH 请求,会发生什么? (为了这个例子,我们假设 /users 资源允许重复的用户名。)"op" 是 "add",所以一个新用户被添加到列表中,随后的 GET /users returns:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" },
 { "id": 3, "username": "newuser", "email": "newuser@example.org" }]

/users 资源已再次更改,即使我们针对完全相同发布了完全相同 PATCH 端点。如果我们的 PATCH 是 f(x),f(f(x)) 与 f(x) 不同,因此,这个特定的 PATCH 不是幂等的.

虽然 PATCH 保证 是幂等的,但 PATCH 规范中没有任何内容可以阻止您在特定服务器上进行所有 PATCH 操作。 RFC 5789 甚至预见到了幂等 PATCH 请求的优势:

A PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame.

在 Dan 的示例中,他的 PATCH 操作实际上是幂等的。在该示例中,/users/1 实体在我们的 PATCH 请求之间发生了变化,但由于 我们的 PATCH 请求而没有 ;实际上是 PostOffice 的 different 补丁文档导致邮政编码发生变化。 Post Office不同的PATCH是不同的操作;如果我们的 PATCH 是 f(x),那么 Post Office 的 PATCH 就是 g(x)。幂等性声明 f(f(f(x))) = f(x),但不保证 f(g(f(x)))

PUT和PATCH的区别在于:

  1. PUT 必须是幂等的。为了实现这一点,您必须将整个完整资源放在请求正文中。
  2. PATCH 可以是非幂等的。这意味着它在某些情况下也可以是幂等的,例如您描述的情况。

PATCH 需要一些 "patch language" 来告诉服务器如何修改资源。调用者和服务器需要定义一些"operations"如"add"、"replace"、"delete"。例如:

GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.com",
  "state": "NY",
  "zip": "10001"
}

PATCH /contacts/1
{
 [{"operation": "add", "field": "address", "value": "123 main street"},
  {"operation": "replace", "field": "email", "value": "abc@myemail.com"},
  {"operation": "delete", "field": "zip"}]
}

GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "abc@myemail.com",
  "state": "NY",
  "address": "123 main street",
}

补丁语言可以通过定义以下约定使其隐含,而不是使用显式 "operation" 字段:

在 PATCH 请求正文中:

  1. 一个字段的存在意味着"replace"或"add"那个字段。
  2. 如果某个字段的值为空,则表示删除该字段。

根据上述约定,示例中的PATCH可以采用以下形式:

PATCH /contacts/1
{
  "address": "123 main street",
  "email": "abc@myemail.com",
  "zip":
}

这样看起来更加简洁易用。但用户需要了解基本约定。

通过我上面提到的操作,PATCH仍然是幂等的。但是如果你定义像这样的操作:"increment" 或 "append",你可以很容易地看到它不再是幂等的。

让我更仔细地引用和评论 RFC 7231 section 4.2.2,已经在之前的评论中引用过:

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent.

(...)

Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response. For example, if a client sends a PUT request and the underlying connection is closed before any response is received, then the client can establish a new connection and retry the idempotent request. It knows that repeating the request will have the same intended effect, even if the original request succeeded, though the response might differ.

那么,一个幂等方法在多次请求后应该“相同”的是什么?不是服务器状态,也不是服务器响应,而是预期效果。特别是,该方法“从客户端的角度来看”应该是幂等的。现在,我认为这个观点表明 , which I don't want to plagiarize here, indeed shows that a PATCH request can be non-idempotent (in a more natural way than the example in ).

中的最后一个例子

的确,让我们通过为第一个客户明确地 intend 使示例稍微精确一些。假设此客户通过该项目的用户列表来检查他们的电子邮件 邮政编码。他从用户 1 开始,注意到 zip 是正确的,但电子邮件是错误的。他决定用一个完全合法的 PATCH 请求来纠正这个问题,并且只发送

PATCH /users/1
{"email": "skwee357@newdomain.com"}

因为这是唯一的更正。现在,请求由于某些网络问题而失败,并在几个小时后自动重新提交。与此同时,另一个客户端(错误地)修改了用户 1 的 zip。然后,第二次发送相同的 PATCH 请求并没有达到客户端的 预期效果 ,因为我们结束了邮编不正确。因此,该方法在 RFC 的意义上不是幂等的。

如果客户端使用 PUT 请求来更正电子邮件,将用户 1 的所有属性与电子邮件一起发送到服务器,即使稍后必须重新发送请求,也能达到预期的效果,并且同时修改了用户 1 --- 因为第二个 PUT 请求将覆盖自第一个请求以来的所有更改。

在我看来,幂等性意味着:

  • 放置:

我发送了一个完整的资源定义,所以 - 生成的资源状态与 PUT 参数定义的完全一样。每次我用相同的 PUT 参数更新资源时——结果状态都是完全一样的。

  • 补丁:

我只发送了部分资源定义,因此其他用户可能会同时更新此资源的其他参数。因此 - 具有相同参数及其值的连续补丁可能会导致不同的资源状态。例如:

假设一个对象定义如下:

汽车: - 颜色:黑色, - 类型:轿车, - 座位数:5

我用它修补:

{颜色:'red'}

生成的对象是:

汽车: - 红色, - 类型:轿车, - 座位数:5

然后,其他一些用户给这辆车打了补丁:

{类型:'hatchback'}

所以,生成的对象是:

汽车: - 红色, - 类型:掀背车, - 座位数:5

现在,如果我再次修补这个对象:

{颜色:'red'}

生成的对象是:

汽车: - 红色, - 类型:掀背车, - 座位数:5

与我之前得到的有什么不同!

这就是 PATCH 不是幂等而 PUT 是幂等的原因。

TLDR - 简化版

PUT => 为现有资源设置所有新属性。

PATCH => 部分更新现有资源(不需要所有属性)。

为了结束关于幂等性的讨论,我应该指出,可以通过两种方式在 REST 上下文中定义幂等性。让我们先把一些事情形式化:

一个resource是一个函数,它的codomain是字符串的class。换句话说,资源是 String × Any 的子集,其中所有键都是唯一的。我们调用资源的 class Res.

对资源的 REST 操作,是一个函数 f(x: Res, y: Res): Res。 REST 操作的两个示例是:

  • PUT(x: Res, y: Res): Res = x,以及
  • PATCH(x: Res, y: Res): Res,其工作方式类似于 PATCH({a: 2}, {a: 1, b: 3}) == {a: 2, b: 3}

(此定义专门用于争论 PUTPOST,例如在 GETPOST 上没有多大意义,因为它不关心持久性)。

现在,通过修复 x: Res(从信息上讲,使用柯里化),PUT(x: Res)PATCH(x: Res)Res → Res.

类型的单变量函数
  1. 一个函数g: Res → Res被称为全局幂等,当g ○ g == g,即对于任何y: Resg(g(y)) = g(y).

  2. x: Res一个资源,k = x.keys。函数 g = f(x) 被称为 左幂等 ,对于每个 y: Res,我们有 g(g(y))|ₖ == g(y)|ₖ。这基本上意味着如果我们查看应用的键,结果应该是相同的。

所以,PATCH(x)不是全局幂等的,而是左幂等的。左幂等性在这里很重要:如果我们修补资源的几个键,我们希望这些键在我们再次修补时相同,我们不关心资源的其余部分。

当 RFC 谈论 PATCH 不是幂等时,它是在谈论全局幂等。好吧,它不是全局幂等的,否则它会是一个失败的操作。


现在, 正试图证明 PATCH 甚至不是幂等的,但它破坏了太多东西:

  • 首先,PATCH 用于集合,尽管 PATCH 被定义为适用于映射/字典/键值对象。
  • 如果有人真的想将 PATCH 应用于集合,那么应该使用自然翻译:t: Set<T> → Map<T, Boolean>,定义为 x in A iff t(A)(x) == True。使用此定义,修补是幂等的。
  • 在示例中,未使用此翻译,而是 PATCH 的工作方式类似于 POST。首先,为什么要为对象生成一个ID?它是什么时候产生的?如果首先将对象与集合的元素进行比较,如果没有找到匹配的对象,则生成 ID,然后程序将再次以不同的方式工作({id: 1, email: "me@site.com"} 必须与 {email: "me@site.com"} 匹配,否则程序总是坏掉,PATCH 不可能打补丁)。如果在检查集合之前生成 ID,则程序再次被破坏。

可以举例说明 PUT 是非幂等的,破坏了本例中破坏的一半内容:

  • 生成附加功能的一个例子是版本控制。人们可能会记录单个对象的更改次数。在这种情况下,PUT 不是幂等的:PUT /user/12 {email: "me@site.com"} 第一次导致 {email: "...", version: 1},第二次 {email: "...", version: 2}
  • 弄乱 ID,每次更新对象时都可能生成一个新的 ID,从而导致非幂等 PUT。

以上例子都是大家可能遇到的自然例子。


我的最后一点是,PATCH 不应该全局幂等,否则不会给你想要的效果。您想要更改用户的电子邮件地址,而不触及其余信息,并且不想覆盖访问同一资源的另一方所做的更改。

我要补充的一个附加信息是,与 PUT 请求相比,PATCH 请求使用的带宽更少,因为只发送了一部分数据,而不是整个实体。因此,只需使用 PATCH 请求更新特定记录(如(1-3 条记录)),而使用 PUT 请求更新大量数据。就是这样,不要想太多,也不要太担心。

其他人都回答了 PUT 与 PATCH。我只是要回答原始问题标题的哪一部分:“......在 REST API 现实生活场景中”。在现实世界中,这发生在我的互联网应用程序中,该应用程序具有 RESTful 服务器和具有“宽”(大约 40 列)客户 table 的关系数据库。我错误地使用了 PUT 但我认为它就像一个 SQL 更新命令并且没有填写所有列。问题:1) 有些列是可选的(因此空白是有效答案),2) 许多列很少更改,3) 不允许用户更改某些列,例如上次购买日期的时间戳,4) 一列是 free-form 文本“评论”栏,用户努力填写 half-page 客户服务评论,例如要询问的配偶姓名或通常的订单,5) 我当时正在开发互联网应用程序,担心数据包大小.

PUT 的缺点是它会强制您发送大量信息(所有列包括整个评论列,即使只更改了一些内容)和 multi-user 2 位以上用户编辑的问题同时是同一位客户(所以最后一个按更新的人获胜)。 PATCH 的缺点是您必须跟踪更改内容的 view/screen 端,并具有一些智能以仅发送更改的部分。 Patch 的 multi-user 问题仅限于编辑同一客户的相同列。

这里有一个很好的解释-

https://blog.segunolalive.com/posts/restful-api-design-%E2%80%94-put-vs-patch/#:~:text=RFC%205789,not%20required%20to%20be%20idempotent.

正常载荷- // 地块 1 上的房子 { 地址:'plot 1', 所有者:'segun', 类型:'duplex', 颜色:'green', 房间:'5', 厨房:'1', windows: 20 } PUT 更新- // PUT 请求负载以更新地块 1 上房屋的 windows { 地址:'plot 1', 所有者:'segun', 类型:'duplex', 颜色:'green', 房间:'5', 厨房:'1', windows: 21 } 注意:在上面的有效载荷中,我们试图将 windows 从 20 更新为 21.

现在查看 PATH 负载- // 修补请求负载以更新 House 上的 windows { windows: 21 }

由于 PATCH 不是幂等的,失败的请求不会自动 re-attempted 在网络上。此外,如果向 non-existent url 发出 PATCH 请求,例如尝试更换 non-existent 建筑物的前门,它应该会简单地失败而不会创建新资源,这与 PUT 不同,PUT 会使用有效载荷创建一个新的。想想看,一个房子的地址只有一扇门会很奇怪。

tl;dr 版本

  • POST:用于创建一个实体

  • PUT:用于 update/replace 现有实体,您 必须发送整个表示 您希望存储的实体

  • PATCH:用于更新一个实体,您只发送需要更新

PUT 方法非常适合以表格格式更新数据,例如在关系数据库或实体(如存储)中。根据用例,它可用于部分更新数据或替换整个实体。这将始终是幂等的。

PATCH 方法可用于更新(或重组)存储在本地文件系统或没有 json 或 xml 格式的数据 sql数据库。这可以通过在请求中提及要执行的 action/operation 来执行,例如 adding/removing/moving 对 json 对象的 key-value 对。删除操作可用于删除 key-value 对,重复请求将导致错误,因为之前删除了密钥,使其成为 non-idempotent 方法。请参阅 RFC 6902 以获取 json 数据修补请求。

这个artical有PATCH方法相关的详细信息。

我会尽量用通俗易懂的语言总结一下我的理解(也许有帮助)

补丁不是完全幂等的(在没有人更改实体的另一个字段的理想情况下)。

在不理想的(现实生活)情况下,有人通过另一个 Patch 操作修改了对象的另一个字段,然后这两个操作都不是幂等的(这意味着你们正在修改的资源从任一点返回“错误”观点)

所以不能覆盖100%的情况就不能称之为幂等。 也许这对某些人来说不是那么重要,但对其他人来说是