2.2.3 HTTP报文格式
HTTP 请求中的 PUT 和 POST 方法均可用于向服务器提交数据,但它们在语义、用途和幂等性上有本质区别。以下是两者的关键差异:
1. 语义与用途
-
PUT
- 作用:用于完整替换服务器上某个已知 URI 对应的资源。
- 场景:客户端明确知道目标资源的 URI(例如
/users/123
),并希望将数据完全覆盖到该位置。 - 示例:更新用户 ID 为 123 的个人信息(如替换整个用户对象)。
-
POST
- 作用:向服务器提交数据,由服务器决定如何处理(如创建新资源、触发操作等)。
- 场景:客户端不明确目标资源的最终 URI,或需要服务器动态生成资源。
- 示例:创建新用户(服务器生成新 ID)、提交表单、上传文件到
/upload
路径。
2. 幂等性(Idempotency)
-
PUT 是幂等的:
- 多次执行同一 PUT 请求,结果与单次执行一致(资源被完全覆盖)。
- 例如:多次 PUT
/users/123
同一数据,最终结果不变。
-
POST 不是幂等的:
- 多次执行同一 POST 请求,可能产生多个资源或不同结果。
- 例如:多次 POST
/users
可能创建多个用户。
3. URI 的确定性
-
PUT
- 客户端必须指定完整的资源 URI(如
/articles/456
)。 - 服务器不会修改 URI,直接覆盖或创建该 URI 对应的资源。
- 客户端必须指定完整的资源 URI(如
-
POST
- 通常向父资源 URI提交数据(如
/articles
),服务器为新资源生成 URI(如/articles/789
)。 - 响应中通过
Location
头返回新资源的 URI(例如201 Created
响应)。
- 通常向父资源 URI提交数据(如
4. 响应状态码
-
PUT
- 成功时通常返回
200 OK
(已存在资源被更新)或201 Created
(新资源被创建)。 - 若仅更新资源,可能返回
204 No Content
(无返回体)。
- 成功时通常返回
-
POST
- 成功时通常返回
201 Created
(新资源被创建),并在Location
头中提供 URI。 - 若触发操作但无新资源,可能返回
200 OK
。
- 成功时通常返回
5. RESTful 设计中的典型应用
-
PUT
- 更新资源(全量替换):
PUT /products/1 { "name": "New Product", "price": 99.99 }
- 更新资源(全量替换):
-
POST
- 创建资源或触发操作:
POST /products { "name": "New Product", "price": 99.99 }
- 服务器返回:
201 Created Location: /products/2
- 服务器返回:
- 创建资源或触发操作:
总结
特性 | PUT | POST |
---|---|---|
幂等性 | 是(多次操作结果一致) | 否(可能产生副作用) |
URI 确定性 | 客户端指定完整 URI | 客户端指定父 URI,服务器生成子 URI |
主要用途 | 替换或创建已知 URI 的资源 | 创建新资源或提交数据触发操作 |
响应码 | 200 OK / 201 Created / 204 No Content | 201 Created / 200 OK |
实际建议:
- 若客户端能控制资源的 URI(如更新操作),优先使用 PUT。
- 若资源 URI 由服务器生成(如创建操作),使用 POST。
- 遵循 RESTful 规范,避免混淆两者的语义。