RESTful API 设计原则

#Web #API #REST #后端开发

RESTful API 设计原则

无状态性 (Stateless)

无状态是指客户端和服务器之间的通信不依赖于历史消息,服务器不存储任何会话状态。每个请求都必须包含处理该请求所需的所有信息。

违反无状态原则的例子:

  • 在用户认证中使用服务器端存储的 session,通过 sessionId 来验证用户信息
  • 服务器存储用户的登录状态或上下文信息

正确的做法:

  • 使用 JWT (JSON Web Token) 进行用户认证
  • 在请求头中携带认证信息(如 Authorization: Bearer
  • 所有必要的状态信息都应由客户端提供

优势:

  • 提高可扩展性:服务器可以轻松水平扩展
  • 提高可靠性:单个服务器故障不会影响用户会话
  • 简化负载均衡:请求可以被路由到任何服务器

可缓存性 (Cacheability)

服务器的响应必须明确地定义自身是否可缓存,以提高性能并减轻服务器负载。

实现方式:

  • 使用 HTTP 缓存头来控制缓存行为
  • Cache-Control: 定义缓存策略(max-age, no-cache, no-store 等)
  • ETag: 资源版本标识符,用于条件请求
  • Last-Modified: 资源最后修改时间

缓存策略示例:

Cache-Control: max-age=3600  # 缓存1小时
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

优势:

  • 减少服务器负载
  • 提高响应速度
  • 降低带宽消耗

统一接口 (Uniform Interface)

统一接口是 REST 架构的核心约束,确保系统组件之间的标准化通信。

资源标识 (Resource Identification)

每个资源都通过 URI 唯一标识,客户端通过 URI 访问和操作资源。

示例:

GET /api/v1/users/123
GET /api/v1/products/456/reviews

通过表述操作资源 (Manipulation of Resources Through Representations)

客户端通过发送资源的表述(如 JSON)来操作资源,而不是直接操作资源本身。

示例:

{
  "name": "John Doe",
  "email": "john@example.com"
}

自描述消息 (Self-descriptive Messages)

每条消息(请求或响应)都应包含足够的信息来描述如何处理它。

实现方式:

  • HTTP 方法:GET、POST、PUT、PATCH、DELETE
  • HTTP 头部:Content-Type、Accept、Authorization
  • HTTP 状态码:200 OK、404 Not Found 等

API 设计实践

资源命名规范

使用名词而非动词

在 REST 理念下,每个 URL 路径都代表一个资源,通过 HTTP 方法来表示操作动作。

良好示例:

- https://api.example.com/v1/zoos
- https://api.example.com/v1/animals
- https://api.example.com/v1/employees

避免的示例:

- https://api.example.com/v1/getUsers
- https://api.example.com/v1/createOrder
- https://api.example.com/v1/deleteProduct

使用复数名词

这是一个常见的约定,用于表示资源集合。

示例:

GET /users          # 获取所有用户
GET /users/123      # 获取特定用户
POST /users         # 创建新用户
PUT /users/123      # 更新用户信息
DELETE /users/123   # 删除用户

使用层级结构

展示资源之间的关系,但避免过深的嵌套。

良好示例:

GET /users/123/orders          # 获取用户 123 的所有订单
GET /users/123/orders/456      # 获取特定用户的特定订单

避免过深嵌套:

# 避免这种过深的嵌套
GET /users/123/orders/456/items/789/reviews/101

HTTP 方法语义

方法 语义 幂等性 安全性
GET 获取资源
POST 创建资源
PUT 更新完整资源
PATCH 部分更新资源
DELETE 删除资源

完整示例:

GET    /zoos                    # 列出所有动物园
POST   /zoos                    # 新建一个动物园
GET    /zoos/123                # 获取指定动物园的信息
PUT    /zoos/123                # 更新指定动物园的完整信息
PATCH  /zoos/123                # 更新指定动物园的部分信息
DELETE /zoos/123                # 删除指定动物园
GET    /zoos/123/animals        # 列出指定动物园的所有动物
DELETE /zoos/123/animals/456    # 删除指定动物园的指定动物

版本控制 (Versioning)

在 API 设计中加入版本控制机制,确保向后兼容性和系统的可扩展性。

实现方式:

  • URL 路径版本控制(推荐):/api/v1/users
  • 查询参数版本控制/api/users?version=1
  • 请求头版本控制Accept: application/vnd.example.v1+json

推荐使用 URL 路径版本控制:

GET /api/v1/users
POST /api/v2/users

优势:

  • 支持并行开发和测试
  • 提供向后兼容性
  • 便于 API 演进和废弃

HTTP 状态码规范

使用标准化的 HTTP 状态码来描述请求的处理结果。

常用状态码

2xx 成功

  • 200 OK - 请求成功
  • 201 Created - 资源创建成功
  • 204 No Content - 请求成功,无返回内容

3xx 重定向

  • 301 Moved Permanently - 资源永久移动
  • 304 Not Modified - 资源未修改(缓存相关)

4xx 客户端错误

  • 400 Bad Request - 请求参数错误
  • 401 Unauthorized - 未认证
  • 403 Forbidden - 无权限
  • 404 Not Found - 资源不存在
  • 409 Conflict - 资源冲突
  • 422 Unprocessable Entity - 请求格式正确但语义错误

5xx 服务器错误

  • 500 Internal Server Error - 服务器内部错误
  • 503 Service Unavailable - 服务不可用

查询参数设计

使用查询参数进行过滤、分页、排序等操作,避免创建复杂的多级 URL。

常用查询参数模式

过滤:

GET /articles?published=true&category=tech
GET /users?status=active&role=admin

分页:

GET /users?page=2&limit=20
GET /products?offset=100&limit=50

排序:

GET /articles?sort=created_at&order=desc
GET /users?sort=name&order=asc

搜索:

GET /products?q=laptop
GET /users?search=john

响应格式标准化

API 响应应该采用结构化的 JSON 格式,保持一致性。

成功响应格式

{
  "status": "success",
  "data": {
    "id": 123,
    "name": "John Doe",
    "email": "john@example.com"
  },
  "meta": {
    "timestamp": "2025-10-10T14:30:00Z",
    "version": "1.0"
  }
}

总结

RESTful API 设计是一个系统性的工程,需要综合考虑架构原则、开发实践和安全性。以下是关键要点:

核心原则

  1. 无状态性 - 每个请求独立,不依赖会话状态
  2. 可缓存性 - 合理利用缓存提高性能
  3. 统一接口 - 标准化通信协议和资源操作

设计要点

  • 使用名词表示资源,HTTP 方法表示操作
  • 采用一致的命名规范和 URL 结构
  • 实现适当的版本控制策略
  • 使用标准的 HTTP 状态码
  • 设计清晰的查询参数模式
  • 保持响应格式的一致性

最佳实践

  • 优先考虑 API 的可发现性和易用性
  • 确保向后兼容性
  • 实施适当的安全措施
  • 提供详细的文档和错误信息

遵循这些原则和实践,可以设计出健壮、可扩展且易于维护的 RESTful API。