PUT
用法
PUT 请求告知服务器将所附带的表示存储在指定的 URI 处。如果资源已存在,服务器会用新的表示替换其全部状态。如果该 URI 处不存在资源,服务器则创建一个。
幂等性
PUT 是幂等的。多次发送相同的 PUT 请求所产生的服务器状态,与只发送一次请求相同。这与 POST 形成对比——重复提交 POST 会创建重复的资源或多次触发处理。
幂等性使 PUT 在网络故障后可以安全地重试。不确定先前请求是否送达的客户端可以再次发送请求,而不会有产生意外副作用的风险。
内容协商
服务器会根据自身约束验证传入的表示。当 Content-Type 符合预期且内容格式正确时,服务器存储资源,并对新资源响应 201 Created,对替换操作响应 200 OK / 204 No Content。
当媒体类型不兼容时,服务器返回 415 Unsupported Media Type。409 Conflict 响应表示与内容类型无关的状态冲突,例如版本不匹配。
PUT 与 POST 对比
POST 将处理工作委托给目标资源。PUT 指定表示所属的确切 URI。对 /articles/42 的 PUT 会将该文章存储在 /articles/42。对 /articles 的 POST 则请求该集合在服务器选定的 URI 处创建一篇新文章。
PUT 与 PATCH 对比
PUT 替换整个资源。PATCH 应用部分修改。用 PUT 更新单个字段需要发送完整的表示。PATCH 则只发送变更部分。
创建资源
客户端将一个纯文本文件存储到 /docs/setup.txt。服务器创建该资源并以 201 Created 响应。
请求
PUT /docs/setup.txt HTTP/1.1
Host: api.example.re
Content-Type: text/plain
Content-Length: 24
Install, configure, run.
响应
HTTP/1.1 201 Created
Location: /docs/setup.txt
Content-Length: 0
替换资源
客户端替换 /users/42 处已有的 JSON 资源。服务器以 200 OK 确认更新并返回存储的表示。
请求
PUT /users/42 HTTP/1.1
Host: api.example.re
Content-Type: application/json
Content-Length: 43
{"name":"Alice","email":"developer@github.com"}
响应
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 51
{"id":42,"name":"Alice","email":"developer@github.com"}
条件更新
使用 If-Match 的条件请求可防止覆盖已被其他客户端修改的资源。ETag 值确保更新仅应用于预期的版本。
请求
PUT /config/app.json HTTP/1.1
Host: api.example.re
Content-Type: application/json
If-Match: "a1b2c3"
Content-Length: 27
{"debug":false,"port":8080}
响应
HTTP/1.1 204 No Content
ETag: "d4e5f6"
CORS
跨域 PUT 请求始终会触发 CORS 预检。浏览器会先发送一个 OPTIONS 请求,以确认服务器允许对目标资源执行 PUT。
响应状态码
201 Created 表示服务器在目标 URI 处创建了一个新资源。这适用于该位置先前不存在资源的情况。
200 OK 确认现有资源已被替换,且响应体中包含更新后的表示。
204 No Content 确认替换成功但没有响应体。当客户端不需要返回存储的表示时,这很常见。
412 Precondition Failed 表示 If-Match 条件未满足。客户端提供的 ETag 值与当前资源版本不匹配,因此服务器拒绝更新,以防止覆盖其他客户端所做的更改。
409 Conflict 表示与前置条件无关的应用层状态冲突,例如内容合并冲突或版本控制碰撞,需要客户端手动解决。