← 返回首页

RESTful API 设计指南

**分类:** Web 协议

**阅读时间:** 约 15 分钟

**最后更新:** 2026-03-27

---

什么是 RESTful API?

REST(Representational State Transfer,表述性状态转移)是一种软件架构风格,由 Roy Fielding 在 2000 年的博士论文中首次提出。RESTful API 是基于 REST 原则设计的 Web API,它使用标准的 HTTP 协议进行通信,具有简洁、可扩展、易于理解等特点。

REST 的六大核心原则

| 原则 | 说明 | 重要性 |

|------|------|--------|

| 客户端 - 服务器(Client-Server) | 关注点分离,客户端负责用户界面,服务器负责数据存储 | 必需 |

| 无状态(Stateless) | 每个请求包含所有必要信息,服务器不保存会话状态 | 必需 |

| 可缓存(Cacheable) | 响应必须定义自身是否可缓存,减少网络交互 | 必需 |

| 统一接口(Uniform Interface) | 资源标识、操作标准化、自描述消息、HATEOAS | 必需 |

| 分层系统(Layered System) | 客户端无法直接判断是否连接到终端服务器 | 必需 |

| 按需代码(Code on Demand) | 服务器可传输可执行代码(如 JavaScript) | 可选 |

---

RESTful API 设计核心规范

RESTful URL 设计规范

flowchart LR
    subgraph Good["✅ 正确示例"]
        G1["GET /users
获取用户列表"] G2["GET /users/123
获取单个用户"] G3["POST /users
创建用户"] G4["PUT /users/123
完整更新用户"] G5["DELETE /users/123
删除用户"] end subgraph Bad["❌ 错误示例"] B1["GET /getUsers"] B2["GET /user?id=123"] B3["POST /createUser"] B4["POST /updateUser?id=123"] B5["POST /deleteUser?id=123"] end

1. 资源命名规范

使用名词,避免动词

**✅ 正确示例:**

GET    /users          # 获取用户列表

POST /users # 创建新用户

GET /users/123 # 获取 ID 为 123 的用户

PUT /users/123 # 更新 ID 为 123 的用户

DELETE /users/123 # 删除 ID 为 123 的用户

**❌ 错误示例:**

GET    /getUsers       # 避免动词

POST /createUser # 避免动词

DELETE /deleteUser/123 # 避免动词

使用复数名词

**✅ 推荐:**

/users      # 用户集合

/articles # 文章集合

/orders # 订单集合

**❌ 不推荐:**

/user       # 单数形式不一致

/article # 单数形式不一致

使用小写字母和连字符

**✅ 推荐:**

/user-profiles

/order-items

/api-docs

**❌ 不推荐:**

/UserProfiles     # 驼峰命名

/user_profiles # 下划线命名

/USER-PROFILES # 大写命名

嵌套资源表示层级关系

**✅ 正确示例:**

GET /users/123/articles        # 获取用户 123 的所有文章

GET /users/123/articles/456 # 获取用户 123 的 ID 为 456 的文章

GET /articles/456/comments # 获取文章 456 的所有评论

**注意:** 嵌套层级不宜超过 3 层,过深的嵌套会使 URL 复杂且难以维护。

---

2. HTTP 方法使用规范

| 方法 | 用途 | 幂等性 | 安全性 |

|------|------|--------|--------|

| GET | 获取资源 | 是 | 是 |

| POST | 创建资源 | 否 | 否 |

| PUT | 更新资源(全量) | 是 | 否 |

| PATCH | 更新资源(部分) | 否* | 否 |

| DELETE | 删除资源 | 是 | 否 |

| HEAD | 获取资源元数据 | 是 | 是 |

| OPTIONS | 获取支持的方法 | 是 | 是 |

*注:PATCH 理论上可以设计为幂等,但通常不是。

GET - 获取资源

GET /users/123 HTTP/1.1

Host: api.example.com

Accept: application/json

**响应示例:**

{

"id": 123,

"name": "张三",

"email": "zhangsan@example.com",

"created_at": "2026-01-15T10:30:00Z"

}

**查询参数使用:**

GET /users?role=admin&status=active&sort=created_at&order=desc

GET /articles?page=2&limit=20

GET /users?fields=id,name,email

POST - 创建资源

POST /users HTTP/1.1

Host: api.example.com

Content-Type: application/json

{

"name": "李四",

"email": "lisi@example.com",

"password": "secure_password_123"

}

**成功响应(201 Created):**

HTTP/1.1 201 Created

Location: /users/456

Content-Type: application/json

{

"id": 456,

"name": "李四",

"email": "lisi@example.com",

"created_at": "2026-03-27T14:30:00Z"

}

PUT - 全量更新资源

PUT /users/123 HTTP/1.1

Host: api.example.com

Content-Type: application/json

{

"id": 123,

"name": "张三更新",

"email": "zhangsan_new@example.com",

"role": "admin"

}

**注意:** PUT 需要提供资源的完整表示,缺失的字段可能会被置为 null。

PATCH - 部分更新资源

PATCH /users/123 HTTP/1.1

Host: api.example.com

Content-Type: application/json

{

"name": "张三更新"

}

**注意:** PATCH 只更新提供的字段,其他字段保持不变。

DELETE - 删除资源

DELETE /users/123 HTTP/1.1

Host: api.example.com

**成功响应(204 No Content):**

HTTP/1.1 204 No Content

---

3. 状态码使用规范

2xx 成功

| 状态码 | 含义 | 使用场景 |

|--------|------|----------|

| 200 OK | 成功 | GET、PUT、PATCH 成功 |

| 201 Created | 已创建 | POST 成功创建资源 |

| 204 No Content | 无内容 | DELETE 成功,或无需返回体的操作 |

3xx 重定向

| 状态码 | 含义 | 使用场景 |

|--------|------|----------|

| 301 Moved Permanently | 永久移动 | 资源 URL 永久变更 |

| 304 Not Modified | 未修改 | 缓存验证通过 |

4xx 客户端错误

| 状态码 | 含义 | 使用场景 |

|--------|------|----------|

| 400 Bad Request | 错误请求 | 请求语法错误、参数无效 |

| 401 Unauthorized | 未授权 | 未提供认证信息 |

| 403 Forbidden | 禁止访问 | 有认证但无权限 |

| 404 Not Found | 未找到 | 资源不存在 |

| 405 Method Not Allowed | 方法不允许 | HTTP 方法不支持 |

| 409 Conflict | 冲突 | 资源冲突(如重复创建) |

| 422 Unprocessable Entity | 无法处理 | 语义错误(如验证失败) |

| 429 Too Many Requests | 请求过多 | 触发限流 |

5xx 服务器错误

| 状态码 | 含义 | 使用场景 |

|--------|------|----------|

| 500 Internal Server Error | 服务器内部错误 | 未预期的服务器错误 |

| 502 Bad Gateway | 网关错误 | 上游服务异常 |

| 503 Service Unavailable | 服务不可用 | 服务过载或维护中 |

---

4. 请求/响应格式规范

统一使用 JSON 格式

**请求头:**

Content-Type: application/json

Accept: application/json

**响应头:**

Content-Type: application/json

统一的响应结构

**成功响应:**

{

"success": true,

"data": {

"id": 123,

"name": "张三"

},

"message": "操作成功"

}

**列表响应:**

{

"success": true,

"data": [

{ "id": 1, "name": "用户 1" },

{ "id": 2, "name": "用户 2" }

],

"pagination": {

"page": 1,

"limit": 20,

"total": 100,

"total_pages": 5

}

}

**错误响应:**

{

"success": false,

"error": {

"code": "VALIDATION_ERROR",

"message": "请求参数验证失败",

"details": [

{

"field": "email",

"message": "邮箱格式不正确"

},

{

"field": "password",

"message": "密码长度至少 8 位"

}

]

}

}

---

5. 版本控制规范

URL 路径版本化(推荐)

GET /api/v1/users

GET /api/v2/users

**优点:** 直观、易于缓存、浏览器地址栏可见

**缺点:** URL 较长

请求头版本化

GET /users HTTP/1.1

Accept: application/vnd.example.v1+json

**优点:** URL 简洁

**缺点:** 不够直观、调试困难

查询参数版本化

GET /users?version=1

**优点:** 简单灵活

**缺点:** 容易被忽略、缓存困难

**最佳实践:** 推荐使用 URL 路径版本化,清晰明确。

---

6. 认证与授权规范

JWT Token 认证(推荐)

**登录获取 Token:**

POST /api/v1/auth/login HTTP/1.1

Content-Type: application/json

{

"username": "admin",

"password": "password123"

}

**响应:**

{

"success": true,

"data": {

"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",

"token_type": "Bearer",

"expires_in": 3600,

"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..."

}

}

**使用 Token 访问受保护资源:**

GET /api/v1/users/123 HTTP/1.1

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

API Key 认证

GET /api/v1/users HTTP/1.1

X-API-Key: your_api_key_here

**适用场景:** 服务端对服务端调用、公开 API

OAuth 2.0 认证

适用于第三方应用授权访问用户资源的场景。

---

7. 分页规范

基于偏移量的分页(Offset-Based)

GET /users?page=2&limit=20

**响应:**

{

"data": [...],

"pagination": {

"page": 2,

"limit": 20,

"offset": 20,

"total": 100,

"total_pages": 5

}

}

**优点:** 简单直观

**缺点:** 深度分页性能差

基于游标的分页(Cursor-Based)

GET /users?cursor=eyJpZCI6MjB9&limit=20

**响应:**

{

"data": [...],

"pagination": {

"limit": 20,

"next_cursor": "eyJpZCI6NDB9",

"prev_cursor": "eyJpZCI6MTB9",

"has_more": true

}

}

**优点:** 性能好、数据一致性高

**缺点:** 无法跳转到指定页

**最佳实践:** 小数据量用偏移量分页,大数据量用游标分页。

---

8. 排序与过滤规范

排序参数

GET /users?sort=created_at&order=desc

GET /articles?sort=title&order=asc

GET /users?sort=-created_at # 负号表示降序

过滤参数

GET /users?role=admin&status=active

GET /articles?category=tech&author=123

GET /users?name_contains=张

GET /articles?created_at_gte=2026-01-01&created_at_lt=2026-12-31

字段选择

GET /users?fields=id,name,email

GET /articles?fields=title,summary,created_at

---

常见错误及解决方案

错误 1:资源命名不一致

**问题:**

GET /getUsers      # 动词 + 名词

POST /user/create # 名词 + 动词

DELETE /user/123 # 单数

**解决方案:** 统一使用复数名词,避免动词

GET    /users

POST /users

DELETE /users/123

---

错误 2:滥用 POST 方法

**问题:**

POST /users/123/delete  # 用 POST 执行删除

POST /users/update # 用 POST 执行更新

**解决方案:** 使用正确的 HTTP 方法

DELETE /users/123

PUT /users/123

---

错误 3:状态码使用不当

**问题:**




所有错误都返回 200,在 body 中表示错误

HTTP/1.1 200 OK

{ "success": false, "error": "Not found" }

**解决方案:** 使用正确的 HTTP 状态码

HTTP/1.1 404 Not Found

{ "error": { "code": "NOT_FOUND", "message": "资源不存在" } }

---

错误 4:缺少版本控制

**问题:**

GET /users  # 无版本标识

**风险:** API 变更时可能破坏现有客户端

**解决方案:** 添加版本控制

GET /api/v1/users

GET /api/v2/users

---

错误 5:响应格式不统一

**问题:**




有时返回数组,有时返回对象

GET /users # 返回 [{...}, {...}]

GET /users/123 # 返回 {...}

GET /users/456 # 返回 { "data": {...} }

**解决方案:** 统一响应结构




列表

{ "data": [...], "pagination": {...} }

单个资源

{ "data": {...} }

错误

{ "error": {...} }

---

安全最佳实践

API 认证方式对比

flowchart LR
    subgraph Auth["认证方式"]
        K1["API Key
简单密钥验证"] K2["Basic Auth
用户名+密码 Base64"] K3["Bearer Token
OAuth2/JWT Token"] K4["OAuth2.0
完整授权流程"] end subgraph Use["推荐场景"] U1["内部服务间调用"] U2["简单 API 验证"] U3["现代 Web/Mobile App"] U4["第三方应用授权"] end K1 --> U1 K2 --> U2 K3 --> U3 K4 --> U4

1. 始终使用 HTTPS

✅ https://api.example.com/users

❌ http://api.example.com/users

2. 输入验证

// 服务端验证示例(Node.js + Express)

app.post('/api/v1/users', (req, res) => {

const { name, email, password } = req.body;

// 验证必填字段

if (!name || !email || !password) {

return res.status(400).json({

error: { code: 'MISSING_FIELDS', message: '缺少必填字段' }

});

}

// 验证邮箱格式

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

if (!emailRegex.test(email)) {

return res.status(400).json({

error: { code: 'INVALID_EMAIL', message: '邮箱格式不正确' }

});

}

// 验证密码强度

if (password.length < 8) {

return res.status(400).json({

error: { code: 'WEAK_PASSWORD', message: '密码长度至少 8 位' }

});

}

// 继续处理...

});

3. 速率限制

X-RateLimit-Limit: 1000        # 每小时请求上限

X-RateLimit-Remaining: 998 # 剩余请求数

X-RateLimit-Reset: 1679904000 # 重置时间戳

**触发限流时:**

HTTP/1.1 429 Too Many Requests

Retry-After: 3600

4. 敏感信息保护

**❌ 不要在响应中返回:**

{

"id": 123,

"name": "张三",

"password": "hashed_password", // 不应返回

"credit_card": "4111-1111-1111-1111" // 不应返回

}

**✅ 正确做法:**

{

"id": 123,

"name": "张三",

"email": "zhangsan@example.com"

}

5. CORS 配置




Nginx CORS 配置示例

add_header Access-Control-Allow-Origin "https://trusted-domain.com";

add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";

add_header Access-Control-Allow-Headers "Content-Type, Authorization";

add_header Access-Control-Allow-Credentials "true";

---

快速参考表

HTTP 方法与 CRUD 对应关系

flowchart TD
    C["Create"] -->|"POST /resources"| N["201 Created"]
    R["Read"] -->|"GET /resources/[id]"| OK200["200 OK"]
    U["Update"] -->|"PUT /resources/[id]
PATCH /resources/[id]"| OK200b["200 OK"] D["Delete"] -->|"DELETE /resources/[id]"| N204["204 No Content"] style C fill:#27ae60,color:#fff style R fill:#3498db,color:#fff style U fill:#f39c12,color:#fff style D fill:#e74c3c,color:#fff

HTTP 方法速查

| 方法 | 用途 | 幂等 | 安全 |

|------|------|------|------|

| GET | 读取资源 | ✅ | ✅ |

| POST | 创建资源 | ❌ | ❌ |

| PUT | 全量更新 | ✅ | ❌ |

| PATCH | 部分更新 | ❌ | ❌ |

| DELETE | 删除资源 | ✅ | ❌ |

状态码速查

| 状态码 | 含义 | 使用场景 |

|--------|------|----------|

| 200 | OK | 成功 |

| 201 | Created | 创建成功 |

| 204 | No Content | 删除成功 |

| 400 | Bad Request | 请求错误 |

| 401 | Unauthorized | 未认证 |

| 403 | Forbidden | 无权限 |

| 404 | Not Found | 未找到 |

| 429 | Too Many Requests | 限流 |

| 500 | Server Error | 服务器错误 |

URL 设计速查

| 场景 | 推荐设计 |

|------|----------|

| 获取列表 | GET /resources |

| 获取单个 | GET /resources/{id} |

| 创建 | POST /resources |

| 全量更新 | PUT /resources/{id} |

| 部分更新 | PATCH /resources/{id} |

| 删除 | DELETE /resources/{id} |

| 嵌套资源 | GET /resources/{id}/sub-resources |

---

相关工具

---

**最后更新:** 2026-03-27

**本文字数:** 约 8500 字

**阅读时间:** 约 15 分钟