2026-08-21 14:58:46.105145+08 / restful-api
HTTP Requests
介绍 RESTful API 中 GET、POST、PUT、PATCH、DELETE 等 HTTP 方法的语义、属性和请求设计实践。
HTTP Requests
RESTful API 使用标准 HTTP 方法定义对资源的操作。API 实现必须遵循 HTTP 方法的标准语义,以保证行为可预测、系统互操作性以及客户端与服务端之间的正确协作。
HTTP 方法语义
GET
GET 请求用于获取资源,可以获取单个资源,也可以获取资源集合。
规则:
- 获取单个资源时,如果资源不存在,应返回
404 Not Found。 - 获取资源集合时,可以返回
200 OK,表示集合存在但不包含元素;如果集合本身不存在,也可以返回404 Not Found。 GET请求不得包含请求体。
示例:
GET /customers/123
响应:
HTTP/1.1 200 OK
{
"id": "123",
"name": "John Smith"
}
对于资源集合,API 应提供过滤和分页机制。
GET /customers?status=active&page=1&pageSize=20
PUT
PUT 请求用于替换完整的资源表示。
其语义是:
使用请求载荷中的表示,替换 URL 所标识的资源。
PUT /customers/123
请求:
{
"id": "123",
"name": "John Smith",
"status": "active"
}
规则:
PUT通常用于单个资源。- 请求载荷表示完整资源。
- 已有资源数据会被新的表示替换。
- 对于未知字段,应忽略而不是保存。
- 成功响应通常返回
200 OK、204 No Content,或者在创建新资源时返回201 Created。
PUT 与资源创建
虽然 PUT 可以创建资源,但创建顶层资源时通常应优先使用 POST。
使用 PUT 创建资源时:
- 资源标识符由客户端控制。
- 重复发送同一个请求必须产生幂等结果。
PUT /customers/customer123
PUT /customers/customer123
API 可以结合 ETag 和 If-Match、If-None-Match 等条件 Header,防止并发更新冲突。
POST
POST 请求主要用于在资源集合下创建新资源。
其语义是:
将请求中包含的表示添加到 URL 所标识的资源集合中。
POST /customers
请求:
{
"name": "John Smith",
"status": "active"
}
响应:
HTTP/1.1 201 Created
Location: /customers/123
{
"id": "123",
"name": "John Smith",
"status": "active"
}
规则:
- 资源标识符通常由服务端生成。
- 响应应提供新创建资源的 URI。
- 常见响应码包括:
201 Created:资源创建成功。202 Accepted:请求已接受,将进行异步处理。200 OK:资源已更新或操作已完成。204 No Content:操作成功,但没有响应体。
与 PUT 不同,重复发送相同的 POST 请求不保证产生相同结果。对于重要场景,API 应考虑让 POST 操作具备幂等性。
PATCH
PATCH 请求用于部分更新已有资源。
其语义是:
根据请求中描述的变更,修改 URL 所标识的资源。
PATCH /customers/123
请求:
{
"status": "inactive"
}
更新后的资源:
{
"id": "123",
"name": "John Smith",
"status": "inactive"
}
规则:
PATCH通常用于单个资源。PATCH通常要求资源已经存在。- 只更新请求中明确指定的字段。
- 成功响应通常返回
200 OK或204 No Content。
推荐的 PATCH 模式
为了避免实现不一致,一个端点应选择一种更新模式。
1. 条件允许时优先使用 PUT
使用完整资源替换:
PUT /customers/123
并提交完整对象。
2. JSON Merge Patch
使用部分对象,并设置:
Content-Type: application/merge-patch+json
{
"status": "inactive"
}
3. JSON Patch
使用基于操作的更新,并设置:
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/status",
"value": "inactive"
}
]
4. 特殊操作使用 POST
如果更新行为无法用 PATCH 语义表达,应使用 POST,并清晰记录其行为。
DELETE
DELETE 请求用于删除资源。
其语义是:
删除 URL 所标识的资源。
成功响应可以是:
HTTP/1.1 204 No Content
也可以返回 200 OK,并在响应中提供已删除资源的信息。
规则:
DELETE通常用于单个资源。- 不建议删除资源集合,因为这意味着删除整个集合。
- 删除后,后续 GET 请求应返回
404 Not Found或410 Gone。 - 被删除的资源不得继续访问。
HEAD
HEAD 与 GET 具有相同语义,但只返回 HTTP Header,不返回响应体。
HEAD /customers/123
典型用途:
- 检查资源是否存在
- 检查元数据
- 验证缓存信息
OPTIONS
OPTIONS 用于发现端点支持的操作。
OPTIONS /customers/123
响应:
Allow: GET, PUT, DELETE
它也可以描述可用操作或支持的能力。
HTTP 方法属性
HTTP 方法具有三个重要属性:
Safe
Safe 操作不会有意修改服务端状态。
Safe 方法包括 GET、HEAD 和 OPTIONS;POST、PUT、PATCH、DELETE 则不是 Safe 方法。
Idempotent
幂等操作在执行一次或多次时,都应产生相同的预期服务端状态。
| 方法 | 幂等 |
|---|---|
| GET | 是 |
| HEAD | 是 |
| PUT | 是 |
| DELETE | 是 |
| POST | 否 |
| PATCH | 不保证 |
例如,多次执行 PUT /customers/123 应产生相同的资源状态。
Cacheable
响应可以被存储并重复使用。通常可缓存的方法是 GET 和 HEAD。某些 POST 响应在明确规定时也可以缓存。
Query Parameters
查询参数应用于资源过滤和简单查询。
GET /customers?name=John
过滤规则应明确:
- 关联的资源属性
- 允许的值范围
- 比较行为
- 组合规则
示例:
name=John
ageGreaterThan=18
createdBefore=2026-01-01
复杂操作
复杂操作应建模为资源,而不是将动词加入 URL。
避免:
POST /customers/searchCustomers
推荐:
POST /customers/searches
请求:
{
"query": "complex search criteria"
}
响应可以返回新建的搜索资源:
{
"id": "search123",
"results": {
"items": []
}
}
异步处理时,可以返回:
HTTP/1.1 202 Accepted
Location: /customers/searches/search123
客户端随后可以查询:
GET /customers/searches/search123
异步请求跟踪
当 API 返回 202 Accepted 时,响应应提供跟踪执行状态的方式。
状态示例:
queued
pending
processing
cancelled
failed
completed
客户端可以持续轮询:
GET /customers/123
直到操作完成。
另一种方式是返回专用的 Job 资源:
{
"job": {
"id": "456",
"href": "/jobs/456",
"status": "processing"
}
}
然后查询:
GET /jobs/456
总结
| 方法 | 用途 | Safe | 幂等 |
|---|---|---|---|
| GET | 读取资源 | 是 | 是 |
| HEAD | 读取元数据 | 是 | 是 |
| POST | 创建资源或执行操作 | 否 | 否 |
| PUT | 替换资源 | 否 | 是 |
| PATCH | 部分更新资源 | 否 | 不保证 |
| DELETE | 删除资源 | 否 | 是 |
| OPTIONS | 发现支持的能力 | 是 | 是 |
REST API 设计应依赖标准 HTTP 语义,而不是创建自定义的动作式端点。这样可以提升可预测性、互操作性、缓存行为以及 API 的长期演进能力。