返回文章列表
技术2026-03-30

API 设计最佳实践

从 RESTful 原则、版本管理、错误格式到认证鉴权和 OpenAPI 文档,设计高质量 API 的完整实践指南。

好 API 的标准是什么

一个好的 API 应该是"自解释"的——开发者不需要反复查阅文档就能理解如何使用。以下是衡量 API 质量的几个维度:

RESTful 设计原则

RESTful API 的核心原则可以归纳为四点:

资源导向(Resource-Oriented)

URL 应该表示资源(名词),而不是操作(动词):

# 好的设计
GET    /articles          # 获取文章列表
GET    /articles/42       # 获取单篇文章
POST   /articles          # 创建文章
PUT    /articles/42       # 更新文章(全量)
PATCH  /articles/42       # 更新文章(部分)
DELETE /articles/42       # 删除文章

# 不好的设计
GET  /getArticles
POST /createArticle
GET  /deleteArticle?id=42

正确使用 HTTP 方法与状态码

# HTTP 方法语义
GET     - 获取资源,安全且幂等
POST    - 创建资源,非幂等
PUT     - 全量替换资源,幂等
PATCH   - 部分更新资源,非幂等
DELETE  - 删除资源,幂等

# HTTP 状态码速查
200 OK            - 请求成功
201 Created       - 资源创建成功
204 No Content    - 删除成功,无返回体
400 Bad Request   - 请求参数错误
401 Unauthorized  - 未认证
403 Forbidden     - 无权限
404 Not Found     - 资源不存在
409 Conflict      - 资源冲突(如重复创建)
422 Unprocessable - 参数验证失败
429 Too Many      - 触发限流
500 Internal Error- 服务器内部错误

版本管理策略

API 版本管理有三种主流方式,各有优劣:

我的推荐是 URL 路径版本。虽然不够纯粹,但它是最实用、最容易被团队理解和调试的方案。Stripe、GitHub、Twilio 等知名 API 都采用这种方式。

# 版本演进示例
GET /v1/users          # v1: 返回基本用户信息
GET /v2/users          # v2: 增加了 avatar、social_links 字段
GET /v1/users          # v1 仍然可用,给调用者迁移时间

错误响应格式:RFC 7807 Problem Details

不要返回纯文本错误信息。使用 RFC 7807 定义的标准化错误格式:

// HTTP 422 Unprocessable Entity
{
  "type": "https://api.example.com/errors/validation-error",
  "title": "Validation Error",
  "status": 422,
  "detail": "请求参数验证失败",
  "instance": "/v1/users",
  "errors": [
    {
      "field": "email",
      "message": "邮箱格式不正确",
      "code": "invalid_format"
    },
    {
      "field": "age",
      "message": "年龄必须在 0 到 150 之间",
      "code": "out_of_range"
    }
  ]
}

这个格式的好处:type 是一个文档 URL,点击可以看到错误的详细说明;errors 数组可以包含多个字段级别的错误,方便前端直接绑定到表单控件。

分页设计:游标 vs 偏移

分页是 API 设计中最容易出问题的地方。两种主流方案:

偏移分页(Offset Pagination)

# 请求
GET /v1/articles?offset=20&limit=10

# 响应
{
  "data": [...],
  "pagination": {
    "offset": 20,
    "limit": 10,
    "total": 157
  }
}

优点:实现简单,支持跳页。缺点:在高并发写入场景下,数据可能重复或遗漏。

游标分页(Cursor Pagination)

# 请求
GET /v1/articles?cursor=eyJpZCI6NDJ9&limit=10

# 响应
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6NTJ9",
    "has_more": true
  }
}

游标分页使用一个不透明的标记(通常是最后一条记录的 ID 编码)来确定下一页的起点。它不受并发写入影响,性能更好(不需要 COUNT(*)),但不支持跳页。

选择建议:数据量大且实时性高(如消息列表、动态流)用游标分页;管理后台、报表系统用偏移分页。

认证与鉴权

JWT(JSON Web Token)

JWT 是目前最流行的无状态认证方案:

# 请求头
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# JWT 结构(Base64 编码)
# Header:  {"alg": "HS256", "typ": "JWT"}
# Payload: {"sub": "123", "name": "Alice", "iat": 1716931200, "exp": 1717017600}
# Signature: HMAC-SHA256(Header + "." + Payload, secret)

JWT 的使用原则:

OAuth 2.0

当你的 API 需要第三方应用访问用户数据时,使用 OAuth 2.0。典型的授权码流程:

# 1. 用户点击"使用 Google 登录"
# 2. 重定向到授权页面
GET https://accounts.google.com/o/oauth2/auth?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=email profile

# 3. 用户同意后,回调带回授权码
# 4. 用授权码换取 Token
POST https://oauth2.googleapis.com/token
{
  "code": "AUTH_CODE",
  "client_id": "...",
  "client_secret": "...",
  "grant_type": "authorization_code"
}

速率限制

不加限制的 API 是脆弱的。常见的限流策略:

# 响应头中返回限流信息
X-RateLimit-Limit: 1000       # 时间窗口内允许的总请求数
X-RateLimit-Remaining: 987    # 剩余可用请求数
X-RateLimit-Reset: 1716934800 # 窗口重置的 Unix 时间戳

# 超限时返回
HTTP 429 Too Many Requests
Retry-After: 60

限流粒度应该分三层:全局(整个 API)、用户级(每个认证用户)、IP 级(未认证请求)。

API 文档与 OpenAPI/Swagger

没有文档的 API 等于不存在。OpenAPI 规范(原 Swagger)是 API 文档的事实标准:

# openapi.yaml
openapi: 3.0.3
info:
  title: Article API
  version: 1.0.0
paths:
  /v1/articles:
    get:
      summary: 获取文章列表
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum: [draft, published, archived]
      responses:
        '200':
          description: 成功返回文章列表
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Article'

工具推荐:

总结

设计一个好的 API 需要的不是炫技,而是纪律。统一的 URL 命名、一致的错误格式、合理的分页策略、清晰的文档——这些看似基础的事情,恰恰是大多数 API 做得不好的地方。从今天开始,给你的 API 加上 RFC 7807 错误格式,写上 OpenAPI 文档,你的调用者会感谢你的。


返回文章列表
标签:API 设计RESTfulOpenAPI