PATCH 和 PUT 请求的主要区别是啥?

Posted

技术标签:

【中文标题】PATCH 和 PUT 请求的主要区别是啥?【英文标题】:What is the main difference between PATCH and PUT request?PATCH 和 PUT 请求的主要区别是什么? 【发布时间】:2014-03-06 19:34:02 【问题描述】:

我在我的 Rails 应用程序中使用PUT 请求。现在,浏览器已经实现了一个新的 HTTP 动词 PATCH。所以,我想知道PATCHPUT 请求之间的主要区别是什么,以及我们何时应该使用其中一个。

【问题讨论】:

【参考方案1】:

HTTP 动词可能是关于 HTTP 协议最神秘的事情之一。它们存在,而且数量很多,但它们为什么存在呢?

Rails 似乎想要支持许多动词并添加一些 Web 浏览器本身不支持的动词。

这里是 http 动词的详尽列表:http://annevankesteren.nl/2007/10/http-methods

这里有来自官方 RFC 的 HTTP 补丁:https://datatracker.ietf.org/doc/rfc5789/?include_text=1

PATCH 方法请求在 请求实体应用于请求标识的资源- URI。更改集以称为“补丁”的格式表示 document”由媒体类型标识。如果 Request-URI 没有 指向一个现有资源,服务器可以创建一个新资源, 取决于补丁文件类型(是否可以在逻辑上修改 一个空资源)和权限等。

PUTPATCH 请求的区别体现在 服务器处理封闭实体以修改资源的方式 由 Request-URI 标识。在 PUT 请求中,包含的实体 被认为是存储在 源服务器,并且客户端请求存储的版本是 更换。 PATCH,然而,封闭的实体包含一组 描述资源当前如何驻留在 应修改源服务器以生成新版本。 PATCH 方法影响由 Request-URI 标识的资源,并且它也 可能对其他资源有副作用;即,新资源可能是 由 PATCH 的应用程序创建或修改现有的。

据我所知,PATCH 动词并没有像在 rails 应用程序中那样使用...据我了解,RFC 补丁动词应该用于发送补丁指令,例如当您做两个文件之间的差异。您无需再次发送整个实体,而是发送一个可能比重新发送整个实体小得多的补丁。

假设您要编辑一个巨大的文件。您编辑 3 行。无需将文件发回,您只需发送差异即可。从好的方面来说,发送补丁请求可用于异步合并文件。版本控制系统可能会使用 PATCH 动词远程更新代码。

另一个可能的用例与 NoSQL 数据库有些相关,可以存储文档。假设我们使用 JSON 结构从服务器到客户端来回发送数据。如果我们想删除一个字段,我们可以使用类似于 mongodb 中 $unset 的语法。实际上,mongodb中用来更新文档的方法很可能是用来处理json补丁的。

举个例子:

db.products.update(
    sku: "unknown" ,
    $unset:  quantity: "", instock: ""  
)

我们可以有这样的东西:

PATCH /products?sku=unknown
 "$unset":  "quantity": "", "instock": ""  

最后但并非最不重要的一点是,人们可以对 HTTP 动词说任何他们想说的话。只有一个真理,真理在 RFC 中。

【讨论】:

请注意,RFC 5789 仍处于提案阶段,尚未被正式接受,目前被标记为“存在错误”。这种“最佳实践”备受争议,从技术上讲,PATCH 还不是 HTTP 标准的一部分。这里唯一的事实是,由于 RFC 未被接受,因此您不应该这样做。 即使还在提案中,也不代表不应该使用。如果是这种情况,我们将无法使用 websockets 和许多其他仍在提案中的 rfcs……实施提案比实施完全自定义的、没有其他人实施的东西要好 100 倍。 BS。它不是“提案中”,它是 HTTP 标准的一部分(标准,RFC 7231 委托给 IANA 注册中心获取方法,PATCH 列在那里)。 @JulianReschke 如果您阅读此 RFC 的第二行,您会发现它仍被标记为 PROPOSED STANDARD。所以不,补丁方法仍在提议中。顺便说一句,rfc 在这里。 tools.ietf.org/html/rfc5789 和 rfc7231 也是建议标准。例如,如果您查看 RFC821,它被标记为 INTERNET STANDARD @JulianReschke en.wikipedia.org/wiki/Internet_Standard#Proposed_Standard ... 这不是我说的。正如我上面解释的那样,提议的标准并不意味着你不能很好地实施它。这并不意味着它不够稳定,无法实施……但它仍在提案中,除非它被标记为 Internet 标准……我不确定你是如何争论的。它被称为“提议的标准”,除了提议之外别无其他含义。如果您想争论可以使用提议的标准。这正是我写的。【参考方案2】:

我在谷歌上花了几个小时找到了答案here

PUT => 如果用户可以更新全部或部分记录,请使用 PUT(用户控制要更新的内容)

PUT /users/123/email
new.email@example.org

补丁 => 如果用户只能更新部分记录,只需说一个电子邮件地址(应用程序控制可以更新的内容),请使用 PATCH。

PATCH /users/123
[description of changes]

为什么Patch

PUT 方法需要更多带宽或部分处理全部资源。所以引入PATCH来减少带宽。

关于PATCH的说明

PATCH 是一种不安全、也不幂等的方法,它允许对其他资源进行全部和部分更新以及副作用。

PATCH 是一种方法,其中包含的实体包含一组指令,描述如何修改当前驻留在源服务器上的资源以生成新版本。

PATCH /users/123
[
   "op": "replace", "path": "/email", "value": "new.email@example.org" 
]

Here 更多关于 put 和 patch 的信息

【讨论】:

为什么这个 PATCH 不安全? PATCH 其中POSTPUT 等不是“安全的”,因为它会修改您的数据(有副作用)。与GETOPTIONS 等(安全方法)相比,您可以多次调用端点而不会产生任何副作用。 PATCH 不是为了节省带宽而引入的。正如 RFC 5789 所述: > “需要一种新方法来提高互操作性并防止错误。”在仅具有包含其余有效负载的 PUT 的多并行环境中,将增加修改资源其他属性的风险。 PATCH 解决了这样的问题。【参考方案3】:

放: 如果我想更新我的 first 名称,那么我会发送 put 请求:

 "first": "Nazmul", "last": "hasan"  

但是使用put 请求存在一个问题:当我想发送put 请求时,我必须发送firstlast 这两个参数(而我只需要更新first ) 所以必须通过put 请求再次发送它们。

补丁:另一方面,patch请求说:只指定data需要的update,不会影响或改变其他数据。 因此无需再次发送所有值。我只需要更改first 名称吗?好吧,在patch 请求中指定first 就足够了。

【讨论】:

IMO,这是最直接的答案。 快速易懂! 我最喜欢的也是,直接开门见山!完美 是的,清晰准确。 ?长话短说?【参考方案4】:

Put 和 Patch 方法类似。但是在rails中它有不同的方法 如果我们想更新/替换整个记录,那么我们必须使用 Put 方法。 如果我们想更新特定记录,请使用 Patch 方法。

【讨论】:

【参考方案5】:

在进行更新时 PUT over PATCH 存在限制。使用 PUT 要求我们指定所有属性,即使我们只想更改一个属性。 但是如果我们使用 PATCH 方法,我们可以只更新我们需要的字段,而无需提及所有字段。 PATCH 不允许我们修改数组中的值,或者删除属性或数组条目。

【讨论】:

【参考方案6】:

PUTPATCH 方法本质上相似,但有一个关键区别。

PUT - 在 PUT 请求中,包含的实体将被视为驻留在服务器上的资源的修改版本,并将被此修改后的实体替换。

PATCH - 在 PATCH 请求中,包含的实体包含一组说明,说明如何修改驻留在服务器上的实体以生成更新的版本。 p>

【讨论】:

【参考方案7】:

根据 HTTP 术语,PUT 请求就像一个数据库更新语句。 PUT - 用于修改现有资源(之前已发布)。另一方面,PATCH 请求用于更新现有资源的某些部分。

例如:

客户详情:

// This is just a example.

firstName = "James";
lastName = "Anderson";
email = "email@domain.com";
phoneNumber = "+92 1234567890";
//..

我们什么时候想更新整个记录?为此,我们必须使用 Http PUT verb

如:

// Customer Details Updated.

firstName = "James++++";
lastName = "Anderson++++";
email = "email@Updated.com";
phoneNumber = "+92 0987654321";
//..

另一方面,如果我们只想更新记录的一部分而不是整个记录,那么选择HttpPATCHverb如:

   // Only Customer firstName and lastName is Updated.

    firstName = "Updated FirstName";
    lastName = "Updated LastName";
   //..

PUT VS POST:

当使用PUT 请求时,我们必须发送所有参数,例如名字、姓氏、电子邮件、电话号码,其中patch 请求只发送我们要更新的参数,它不会影响或更改其他参数数据。

更多详情请访问:https://fullstack-developer.academy/restful-api-design-post-vs-put-vs-patch/

【讨论】:

【参考方案8】:

以下是 HTTP 协议的 POST、PUT 和 PATCH 方法之间的区别。

发布

HTTP.POST 方法总是在服务器上创建一个新资源。它是一个非幂等请求,即如果用户点击相同的请求 2 次,如果没有约束,它将创建另一个新资源。

http post 方法就像 SQL 中的 INSERT 查询,它总是在数据库中创建一条新记录。

示例:使用 POST 方法保存新用户、订单等,其中后端服务器决定新资源的资源 ID。

PUT

在 HTTP.PUT 方法中,首先从 URL 中识别资源,如果存在则更新它,否则创建一个新资源。当目标资源存在时,它会用一个完整的新主体覆盖该资源。即 HTTP.PUT 方法用于创建或更新资源。

http put 方法类似于 SQL 中的 MERGE 查询,它根据给定记录是否存在来插入或更新记录。

PUT 请求是幂等的,即两次点击相同的请求将更新现有记录(不创建新记录)。在 PUT 方法中,资源 id 由客户端决定并在请求 url 中提供。

示例:使用 PUT 方法更新现有用户或订单。

补丁

HTTP.PATCH 方法用于对资源的部分修改,即增量更新。

http patch 方法类似于 SQL 中的 UPDATE 查询,它只设置或更新选定的列,而不是整行。

示例:您可以使用 PATCH 方法更新订单状态。

补丁/api/users/40450236/order/10234557

请求正文:status: 'Delivered'

【讨论】:

干得好!不言自明【参考方案9】:

PUT 和 PATCH 的区别 PUT 和 PATCH 请求之间的主要区别在于服务器处理封闭实体以更新由 Request-URI 标识的资源的方式。发出 PUT 请求时,封闭的实体被视为原始服务器上保存的资源的修改版本,客户端请求替换它。但是,对于 PATCH,封闭的实体拥有一组说明,这些说明描述了如何对存储在原始服务器上的资源进行部分修改以创建新版本。

第二个区别在于幂等性。 HTTP PUT 被认为是幂等的,因为它在每次发出多个请求后总是产生相同的结果。另一方面,HTTP PATCH 基本上可以说是非幂等的。但是,可以根据实现的位置使其具有幂等性。

【讨论】:

【参考方案10】:

类比说明

Hungry Jack's(墨尔本的一家汉堡连锁店)在处理有问题的订单时使用 put/patch 请求:

我点了一个汉堡。肉有点陈旧。

(A) 提出请求

通常,他们会全部替换坏汉堡:这就像一个放置请求。

(B) 补丁请求

或者他们可以用更新鲜的肉饼代替不新鲜的肉,剩下的就是我原来吃的面包、生菜、番茄酱等等。

在这种特殊情况下,用 put 请求完全替换资源(即汉堡)要容易得多。

但是,您可以看到补丁请求可能会有所帮助:

例如如果我的大型天空刮板有一个小缺陷 - 也许修补缺陷比完全更换天空刮板更容易。

【讨论】:

以上是关于PATCH 和 PUT 请求的主要区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot接口同时支持PATCH和PUT请求

如何在 Yandex Tank 中发出 PUT/PATCH/DELETE 请求?

get,post,patch,put,delete,head,options

put请求(单整体改),patch请求(群单改,群改)

如何在一条路线中使用 PUT 和 PATCH 请求创建另一个更新功能?

Put和Post in Rest之间的区别[重复]