HTTPQUERY
English

PATCH

用法

PATCH 请求发送一组指令,描述如何修改现有资源。与替换整个资源的 PUT 不同,PATCH 仅更改指定的字段或属性。

请求体包含一份服务器能够理解的补丁文档。Content-Type 请求头标识补丁格式。服务器响应中的 Accept-Patch 请求头则声明所支持的补丁格式。

注意

PATCH 并未被废弃。该方法于 2010 年标准化,至今仍是 HTTP 语义中活跃的一部分。产生混淆的原因在于 PATCH 比其他方法出现得晚,且一些较旧的框架缺乏原生支持。

注意

PATCH 不保证幂等性。两次应用相同的补丁可能产生不同的结果(例如两次向列表追加元素)。在不使用条件请求(If-Unmodified-Since 或 If-Match)的情况下,对同一资源的并发补丁存在冲突风险。

常见补丁格式

JSON Patch 将修改表示为一个有序的操作数组:add、remove、replace、move、copy 和 test。

Content-Type: application/json-patch+json

[
  {"op":"replace","path":"/email",
   "value":"developer@github.com"},
  {"op":"add","path":"/verified","value":true}
]

JSON Merge Patch 采用更简单的方式。补丁文档与目标资源结构相对应。补丁中存在的字段会覆盖现有值。将字段设为 null 则会移除该字段。

Content-Type: application/merge-patch+json

{"email":"developer@github.com","nickname":null}

原子性

服务器将补丁文档中的所有更改作为单个原子操作应用。如果任何一条指令失败,整个补丁都会被拒绝,资源保持不变。

注意

PATCH 请求具有副作用,且不保证幂等。对”向列表追加”操作依次应用两个相同的补丁,其结果与仅应用一次不同。

JSON Merge Patch

客户端使用 JSON Merge Patch 格式更新用户 42 的电子邮件地址。服务器应用更改并返回 200 OK 及更新后的资源。

请求

PATCH /users/42 HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
Content-Length: 28

{"email":"developer@github.com"}

响应

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 51

{"id":42,"name":"Alice","email":"developer@github.com"}

JSON Patch

客户端对配置资源应用两个操作:替换 debug 标志并添加一个新的日志级别字段。服务器以 204 No Content 确认。

请求

PATCH /config/app HTTP/1.1
Host: api.example.re
Content-Type: application/json-patch+json
Content-Length: 102

[
  {"op":"replace","path":"/debug","value":false},
  {"op":"add","path":"/logLevel","value":"warn"}
]

响应

HTTP/1.1 204 No Content

条件补丁

使用 If-Unmodified-Since 的条件请求可防止修改已被其他客户端更改的资源。如果资源在给定时间戳之后被修改,服务器返回 412 Precondition Failed。

请求

PATCH /docs/report.json HTTP/1.1
Host: api.example.re
Content-Type: application/merge-patch+json
If-Unmodified-Since: Mon, 01 Jan 2024 12:00:00 GMT
Content-Length: 21

{"status":"reviewed"}

响应

HTTP/1.1 412 Precondition Failed
Content-Length: 0

CORS

跨域 PATCH 请求始终会触发 CORS 预检。浏览器会先发送一个 OPTIONS 请求,以确认服务器允许对目标资源执行 PATCH。

PATCH 与 PUT 对比

PATCH 只发送变更部分,使请求更小,对于大型资源而言更节省带宽。PUT 每次都发送完整表示,无论有多少字段发生了变化。

PUT 是幂等的。发送两次相同的 PUT 请求会产生相同的服务器状态。PATCH 不保证幂等,因为像向列表追加元素这样的操作每次应用都会产生不同的结果。

在更新现有资源上的特定字段时使用 PATCH。在用新表示替换整个资源时使用 PUT。

PATCH 与 POST 对比

PATCH 修改已知 URI 处的现有资源。POST 创建新资源或触发服务器端处理。

PATCH 使用已定义的补丁语义,例如 JSON Patch 和 JSON Merge Patch。POST 将语义完全委托给服务器,对请求体没有规定的格式。