HTTP 方法使用 #
概述 #
HTTP 方法定义了对资源的操作类型。在 RESTful API 中,正确使用 HTTP 方法是设计良好 API 的关键。
text
┌─────────────────────────────────────────────────────────────┐
│ HTTP 方法概览 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 方法 操作 幂等性 安全性 可缓存 │
│ ───────────────────────────────────────────────────────── │
│ GET 查询 ✅ ✅ ✅ │
│ POST 创建 ❌ ❌ ⚠️ │
│ PUT 完整更新 ✅ ❌ ❌ │
│ PATCH 部分更新 ❌ ❌ ❌ │
│ DELETE 删除 ✅ ❌ ❌ │
│ HEAD 查询头 ✅ ✅ ✅ │
│ OPTIONS 查询选项 ✅ ✅ ❌ │
│ │
│ 幂等性:多次执行结果相同 │
│ 安全性:不会修改资源状态 │
│ 可缓存:响应可被缓存 │
│ │
└─────────────────────────────────────────────────────────────┘
GET 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ GET 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:获取资源的表述 │
│ │
│ 特性: │
│ ✅ 安全(Safe):不修改资源状态 │
│ ✅ 幂等(Idempotent):多次请求结果相同 │
│ ✅ 可缓存(Cacheable):响应可被缓存 │
│ │
│ 使用场景: │
│ - 获取资源列表 │
│ - 获取单个资源详情 │
│ - 搜索资源 │
│ - 查询操作 │
│ │
└─────────────────────────────────────────────────────────────┘
GET 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ GET 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 获取资源列表: │
│ GET /users HTTP/1.1 │
│ Host: api.example.com │
│ Accept: application/json │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ │
│ { │
│ "data": [ │
│ { "id": 1, "name": "张三" }, │
│ { "id": 2, "name": "李四" } │
│ ], │
│ "pagination": { │
│ "page": 1, │
│ "limit": 20, │
│ "total": 100 │
│ } │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 获取单个资源: │
│ GET /users/123 HTTP/1.1 │
│ Host: api.example.com │
│ Accept: application/json │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ │
│ { │
│ "id": 123, │
│ "name": "张三", │
│ "email": "zhangsan@example.com" │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 带查询参数: │
│ GET /users?status=active&sort=-createdAt&page=1&limit=20 │
│ │
└─────────────────────────────────────────────────────────────┘
GET 方法最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ GET 方法最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 正确做法: │
│ │
│ 1. 使用查询参数传递过滤条件 │
│ GET /users?status=active │
│ │
│ 2. 利用缓存提高性能 │
│ GET /users/123 │
│ If-None-Match: "etag-value" │
│ │
│ 3. 支持字段选择 │
│ GET /users?fields=id,name,email │
│ │
│ ❌ 错误做法: │
│ │
│ 1. 使用 GET 修改数据 │
│ GET /users/123/delete ❌ │
│ │
│ 2. 在请求体中传递数据 │
│ GET /users │
│ Body: { "status": "active" } ❌ │
│ │
│ 3. 传递敏感信息 │
│ GET /users?password=xxx ❌ │
│ │
└─────────────────────────────────────────────────────────────┘
POST 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ POST 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:创建新资源 │
│ │
│ 特性: │
│ ❌ 非安全:会修改资源状态 │
│ ❌ 非幂等:多次请求创建多个资源 │
│ ⚠️ 可缓存:仅当包含新鲜度信息时可缓存 │
│ │
│ 使用场景: │
│ - 创建新资源 │
│ - 复杂查询(查询条件太长) │
│ - 执行操作(非 CRUD) │
│ - 文件上传 │
│ │
└─────────────────────────────────────────────────────────────┘
POST 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ POST 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 创建资源: │
│ POST /users HTTP/1.1 │
│ Host: api.example.com │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "password": "securePassword123" │
│ } │
│ │
│ 响应: │
│ HTTP/1.1 201 Created │
│ Location: https://api.example.com/users/124 │
│ Content-Type: application/json │
│ │
│ { │
│ "id": 124, │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "createdAt": "2025-03-29T10:30:00Z" │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 复杂查询(POST 搜索): │
│ POST /search HTTP/1.1 │
│ Content-Type: application/json │
│ │
│ { │
│ "query": "iPhone", │
│ "filters": { │
│ "category": "electronics", │
│ "priceRange": { "min": 100, "max": 1000 } │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
POST 方法最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ POST 方法最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 正确做法: │
│ │
│ 1. 返回 201 Created 状态码 │
│ HTTP/1.1 201 Created │
│ │
│ 2. 返回 Location 头 │
│ Location: https://api.example.com/users/124 │
│ │
│ 3. 返回创建的资源 │
│ { "id": 124, "name": "张三" } │
│ │
│ 4. 使用请求体传递数据 │
│ { "name": "张三", "email": "..." } │
│ │
│ ❌ 错误做法: │
│ │
│ 1. 使用 GET 参数传递创建数据 │
│ POST /users?name=张三&email=... ❌ │
│ │
│ 2. 返回 200 OK 而非 201 Created │
│ HTTP/1.1 200 OK ❌ │
│ │
│ 3. 不返回 Location 头 │
│ 客户端无法知道新资源位置 ❌ │
│ │
└─────────────────────────────────────────────────────────────┘
PUT 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ PUT 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:完整更新资源 │
│ │
│ 特性: │
│ ❌ 非安全:会修改资源状态 │
│ ✅ 幂等:多次请求结果相同 │
│ ❌ 不可缓存 │
│ │
│ 使用场景: │
│ - 完整更新资源 │
│ - 创建指定 ID 的资源(Upsert) │
│ │
│ 注意: │
│ - 必须提供资源的完整数据 │
│ - 未提供的字段会被清空或设为默认值 │
│ │
└─────────────────────────────────────────────────────────────┘
PUT 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ PUT 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 完整更新资源: │
│ PUT /users/123 HTTP/1.1 │
│ Host: api.example.com │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "李四", │
│ "email": "lisi@example.com", │
│ "status": "active" │
│ } │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ │
│ { │
│ "id": 123, │
│ "name": "李四", │
│ "email": "lisi@example.com", │
│ "status": "active", │
│ "updatedAt": "2025-03-29T11:00:00Z" │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ Upsert(创建或更新): │
│ PUT /users/123 HTTP/1.1 │
│ │
│ 如果资源存在:更新,返回 200 OK │
│ 如果资源不存在:创建,返回 201 Created │
│ │
└─────────────────────────────────────────────────────────────┘
PUT vs PATCH #
text
┌─────────────────────────────────────────────────────────────┐
│ PUT vs PATCH │
├─────────────────────────────────────────────────────────────┤
│ │
│ PUT:完整更新 │
│ ───────────────────────────────────────────── │
│ PUT /users/123 │
│ { │
│ "name": "李四", // 必须提供 │
│ "email": "lisi@example.com", // 必须提供 │
│ "status": "active" // 必须提供 │
│ } │
│ │
│ 结果:所有字段都被更新,未提供的字段被清空 │
│ │
│ ───────────────────────────────────────────── │
│ │
│ PATCH:部分更新 │
│ ───────────────────────────────────────────── │
│ PATCH /users/123 │
│ { │
│ "name": "王五" // 只提供需要更新的字段 │
│ } │
│ │
│ 结果:只更新 name 字段,其他字段保持不变 │
│ │
└─────────────────────────────────────────────────────────────┘
PATCH 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ PATCH 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:部分更新资源 │
│ │
│ 特性: │
│ ❌ 非安全:会修改资源状态 │
│ ❌ 非幂等:取决于实现方式 │
│ ❌ 不可缓存 │
│ │
│ 使用场景: │
│ - 部分更新资源 │
│ - 修改少量字段 │
│ │
│ 注意: │
│ - 只需提供需要更新的字段 │
│ - 未提供的字段保持不变 │
│ │
└─────────────────────────────────────────────────────────────┘
PATCH 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ PATCH 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 部分更新资源: │
│ PATCH /users/123 HTTP/1.1 │
│ Host: api.example.com │
│ Content-Type: application/json │
│ │
│ { │
│ "name": "王五" │
│ } │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ │
│ { │
│ "id": 123, │
│ "name": "王五", // 已更新 │
│ "email": "zhangsan@example.com", // 保持不变 │
│ "status": "active", // 保持不变 │
│ "updatedAt": "2025-03-29T11:30:00Z" │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ JSON Patch 格式(RFC 6902): │
│ PATCH /users/123 HTTP/1.1 │
│ Content-Type: application/json-patch+json │
│ │
│ [ │
│ { "op": "replace", "path": "/name", "value": "王五" }, │
│ { "op": "add", "path": "/tags/-", "value": "vip" }, │
│ { "op": "remove", "path": "/temp" } │
│ ] │
│ │
└─────────────────────────────────────────────────────────────┘
DELETE 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ DELETE 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:删除资源 │
│ │
│ 特性: │
│ ❌ 非安全:会修改资源状态 │
│ ✅ 幂等:删除同一资源多次结果相同 │
│ ❌ 不可缓存 │
│ │
│ 使用场景: │
│ - 删除单个资源 │
│ - 批量删除资源 │
│ │
│ 注意: │
│ - 删除不存在的资源应返回 404 或 204 │
│ - 考虑软删除(标记删除而非物理删除) │
│ │
└─────────────────────────────────────────────────────────────┘
DELETE 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ DELETE 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 删除资源: │
│ DELETE /users/123 HTTP/1.1 │
│ Host: api.example.com │
│ Authorization: Bearer eyJhbGciOiJIUzI1NiIs... │
│ │
│ 响应方式一:返回 204 No Content │
│ HTTP/1.1 204 No Content │
│ │
│ 响应方式二:返回 200 OK + 删除的资源信息 │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ │
│ { │
│ "id": 123, │
│ "deleted": true, │
│ "deletedAt": "2025-03-29T12:00:00Z" │
│ } │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 批量删除: │
│ DELETE /users?ids=1,2,3 HTTP/1.1 │
│ │
│ 或 │
│ │
│ POST /users/batch-delete HTTP/1.1 │
│ Content-Type: application/json │
│ │
│ { │
│ "ids": [1, 2, 3] │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
HEAD 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ HEAD 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:获取资源的元数据(响应头) │
│ │
│ 特性: │
│ ✅ 安全:不修改资源状态 │
│ ✅ 幂等:多次请求结果相同 │
│ ✅ 可缓存 │
│ │
│ 使用场景: │
│ - 检查资源是否存在 │
│ - 检查资源是否被修改 │
│ - 获取资源大小 │
│ - 获取 Content-Type │
│ │
└─────────────────────────────────────────────────────────────┘
HEAD 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ HEAD 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 检查资源是否存在: │
│ HEAD /users/123 HTTP/1.1 │
│ Host: api.example.com │
│ │
│ 响应(资源存在): │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ Content-Length: 256 │
│ ETag: "33a64df551425fcc55e4d42a148795d9" │
│ Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT │
│ │
│ 响应(资源不存在): │
│ HTTP/1.1 404 Not Found │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 检查资源是否被修改: │
│ HEAD /users/123 HTTP/1.1 │
│ If-None-Match: "old-etag-value" │
│ │
│ 响应(未修改): │
│ HTTP/1.1 304 Not Modified │
│ │
└─────────────────────────────────────────────────────────────┘
OPTIONS 方法 #
基本语义 #
text
┌─────────────────────────────────────────────────────────────┐
│ OPTIONS 方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 语义:获取资源支持的 HTTP 方法 │
│ │
│ 特性: │
│ ✅ 安全:不修改资源状态 │
│ ✅ 幂等:多次请求结果相同 │
│ ❌ 不可缓存 │
│ │
│ 使用场景: │
│ - CORS 预检请求 │
│ - API 发现 │
│ - 查询支持的 HTTP 方法 │
│ │
└─────────────────────────────────────────────────────────────┘
OPTIONS 请求示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ OPTIONS 请求示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ CORS 预检请求: │
│ OPTIONS /users HTTP/1.1 │
│ Host: api.example.com │
│ Origin: https://client.example.com │
│ Access-Control-Request-Method: POST │
│ Access-Control-Request-Headers: Content-Type │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Access-Control-Allow-Origin: https://client.example.com │
│ Access-Control-Allow-Methods: GET, POST, PUT, DELETE │
│ Access-Control-Allow-Headers: Content-Type, Authorization │
│ Access-Control-Max-Age: 86400 │
│ Allow: GET, POST, PUT, DELETE, OPTIONS │
│ │
│ ───────────────────────────────────────────── │
│ │
│ 查询支持的 HTTP 方法: │
│ OPTIONS /users/123 HTTP/1.1 │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Allow: GET, PUT, DELETE, PATCH, HEAD, OPTIONS │
│ │
└─────────────────────────────────────────────────────────────┘
方法选择指南 #
场景对照表 #
text
┌─────────────────────────────────────────────────────────────┐
│ 方法选择指南 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 场景 推荐方法 说明 │
│ ───────────────────────────────────────────────────────── │
│ 获取资源列表 GET 安全、可缓存 │
│ 获取单个资源 GET 安全、可缓存 │
│ 创建新资源 POST 返回 201 Created │
│ 完整更新资源 PUT 幂等 │
│ 部分更新资源 PATCH 只更新指定字段 │
│ 删除资源 DELETE 幂等 │
│ 检查资源是否存在 HEAD 不返回响应体 │
│ 查询支持的 HTTP 方法 OPTIONS CORS 预检 │
│ 复杂查询 POST 查询条件太长时 │
│ 文件上传 POST multipart/form-data │
│ 批量操作 POST 非标准 CRUD │
│ │
└─────────────────────────────────────────────────────────────┘
方法对比总结 #
text
┌─────────────────────────────────────────────────────────────┐
│ 方法对比总结 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 方法 请求体 响应体 幂等性 安全性 典型状态码 │
│ ───────────────────────────────────────────────────────── │
│ GET ❌ ✅ ✅ ✅ 200, 404 │
│ POST ✅ ✅ ❌ ❌ 201, 400 │
│ PUT ✅ ✅ ✅ ❌ 200, 204 │
│ PATCH ✅ ✅ ❌ ❌ 200, 204 │
│ DELETE ❌ ⚠️ ✅ ❌ 204, 200 │
│ HEAD ❌ ❌ ✅ ✅ 200, 404 │
│ OPTIONS ❌ ⚠️ ✅ ✅ 200 │
│ │
│ ⚠️ 表示可选 │
│ │
└─────────────────────────────────────────────────────────────┘
方法使用检查清单 #
text
□ GET 方法
□ 用于查询操作
□ 不修改资源状态
□ 参数通过 URL 传递
□ 支持缓存
□ POST 方法
□ 用于创建资源
□ 返回 201 Created
□ 返回 Location 头
□ 数据通过请求体传递
□ PUT 方法
□ 用于完整更新
□ 提供完整资源数据
□ 幂等性保证
□ PATCH 方法
□ 用于部分更新
□ 只提供需要更新的字段
□ 未提供字段保持不变
□ DELETE 方法
□ 用于删除资源
□ 返回 204 或 200
□ 幂等性保证
□ HEAD 方法
□ 用于获取元数据
□ 不返回响应体
□ OPTIONS 方法
□ 用于 CORS 预检
□ 返回 Allow 头
下一步 #
现在你已经了解了 HTTP 方法的正确使用,接下来学习 状态码使用,深入了解如何正确使用 HTTP 状态码!
最后更新:2026-03-29