𝑻𝒆𝒏𝑪𝒍𝒂𝒘正在头脑风暴···
𝑻𝒆𝒏𝑲𝒊𝑺𝒆𝒀𝒂の𝑨𝒈𝒆𝒏𝒕助手
𝑻𝒆𝒏-𝒇𝒍𝒂𝒔𝒉

API 设计与 RESTful 规范

良好的 API 设计是现代应用架构的核心,RESTful 风格是目前最流行的 API 设计规范。

RESTful 基础概念

REST 架构原则

  1. 客户端-服务器分离:客户端和服务器端独立演进
  2. 无状态:每个请求包含所有必要信息
  3. 可缓存:响应应明确标明可缓存性
  4. 统一接口:标准的接口约定
  5. 分层系统:中间层不影响直接通信
  6. 按需代码:服务器可向客户端传输可执行代码

资源与 URI 设计

# 好的 URI 设计
GET /api/v1/users # 获取用户列表
GET /api/v1/users/123 # 获取特定用户
POST /api/v1/users # 创建用户
PUT /api/v1/users/123 # 更新用户
DELETE /api/v1/users/123 # 删除用户

# 资源关系
GET /api/v1/users/123/orders # 获取用户的订单
GET /api/v1/orders/456/items # 获取订单的项目
POST /api/v1/users/123/orders # 为用户创建订单

# 避免的设计
GET /api/v1/getUsers # 不使用动词
GET /api/v1/users.php # 不使用文件扩展名
GET /api/v1/user_data # 使用复数形式

HTTP 方法使用

标准 HTTP 方法

方法操作幂等性安全性示例
GET查询GET /users
POST创建POST /users
PUT完整更新PUT /users/123
PATCH部分更新PATCH /users/123
DELETE删除DELETE /users/123
HEAD获取头信息HEAD /users
OPTIONS获取选项OPTIONS /users

实际应用示例

# 创建资源
POST /api/v1/users
Content-Type: application/json

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

# 响应
HTTP/1.1 201 Created
Location: /api/v1/users/123
Content-Type: application/json

{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-12-15T10:30:00Z"
}

# 更新资源
PUT /api/v1/users/123
Content-Type: application/json

{
"name": "John Smith",
"email": "johnsmith@example.com"
}

# 部分更新
PATCH /api/v1/users/123
Content-Type: application/json-patch+json

[
{ "op": "replace", "path": "/name", "value": "John Smith" },
{ "op": "add", "path": "/phone", "value": "+1234567890" }
]

状态码规范

常用状态码

# 成功响应
200 OK # 请求成功
201 Created # 资源创建成功
204 No Content # 成功但无内容返回

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

# 服务器错误
500 Internal Server Error # 服务器内部错误
502 Bad Gateway # 网关错误
503 Service Unavailable # 服务不可用

错误响应格式

// 标准错误响应
{
"error": {
"code": "USER_NOT_FOUND",
"message": "User with ID 123 not found",
"details": {
"userId": 123,
"timestamp": "2024-12-15T10:30:00Z"
}
}
}

// 验证错误响应
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"fields": {
"email": "Invalid email format",
"password": "Password must be at least 8 characters"
}
}
}
}

数据格式设计

请求响应格式

// 列表响应格式
{
"data": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
{
"id": 2,
"name": "Jane Smith",
"email": "jane@example.com"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 100,
"totalPages": 5
},
"links": {
"self": "/api/v1/users?page=1&limit=20",
"next": "/api/v1/users?page=2&limit=20",
"last": "/api/v1/users?page=5&limit=20"
}
}

// 单个资源响应格式
{
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-12-15T10:30:00Z",
"updatedAt": "2024-12-15T11:00:00Z"
},
"included": {
"profile": {
"bio": "Software Developer",
"avatar": "/avatars/1.jpg"
}
}
}

分页参数

# 基于偏移的分页
GET /api/v1/users?page=2&limit=20

# 基于游标的分页
GET /api/v1/users?after=eyJpZCI6IDEwMH0=&limit=20

# 时间分页
GET /api/v1/users?since=2024-12-01T00:00:00Z&until=2024-12-31T23:59:59Z

认证与授权

API 密钥认证

# 请求头中的 API 密钥
GET /api/v1/users
Authorization: Bearer abc123def456
X-API-Key: your-api-key-here

# 查询参数中的 API 密钥
GET /api/v1/users?api_key=abc123def456

JWT 认证

# 获取 Token
POST /api/v1/auth/login
Content-Type: application/json

{
"email": "user@example.com",
"password": "password"
}

# 响应
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}

# 使用 Token
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

OAuth2 授权

# 授权码流程
GET /oauth/authorize?response_type=code&client_id=123&redirect_uri=https://app.com/callback&scope=read&state=xyz

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=abc123&client_id=123&client_secret=secret&redirect_uri=https://app.com/callback

版本控制

URI 版本控制

# 最常用的版本控制方式
GET /api/v1/users
GET /api/v2/users

# 版本特性差异
# v1: GET /api/v1/users (返回 basic info)
# v2: GET /api/v2/users (返回 extended info with relationships)

请求头版本控制

# 使用 Accept 头
GET /api/users
Accept: application/vnd.api+json;version=1

# 使用自定义头
GET /api/users
API-Version: v1

查询参数版本控制

GET /api/users?version=v1
GET /api/users?version=v2

缓存策略

缓存控制头

# 强缓存
GET /api/v1/users/123
Cache-Control: public, max-age=3600
ETag: "abc123"

# 条件请求
GET /api/v1/users/123
If-None-Match: "abc123"

# 响应
HTTP/1.1 304 Not Modified

# 不缓存
GET /api/v1/users/current
Cache-Control: no-cache, no-store, must-revalidate

缓存键设计

# 基础缓存键
users:list:page:1:limit:20
users:123:detail

# 用户特定缓存
users:123:detail:role:admin

# 组合缓存
users:list:filter:active:sort:name

限流与配额

限流响应头

GET /api/v1/users
X-RateLimit-Limit: 1000 # 总限制
X-RateLimit-Remaining: 999 # 剩余次数
X-RateLimit-Reset: 1640995200 # 重置时间戳

# 超限响应
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 60

限流实现

# Python Flask 示例
from flask_limiter import Limiter
from flask import Flask

app = Flask(__name__)
limiter = Limiter(
app,
key_func=lambda: request.headers.get('X-API-Key') or request.remote_addr
)

@app.route('/api/v1/users')
@limiter.limit("100 per hour")
def get_users():
return jsonify(users_data)

# 不同用户不同限制
@app.route('/api/v1/premium/users')
@limiter.limit("1000 per hour", key_func=lambda: 'premium')
def get_premium_users():
return jsonify(premium_users)

文档与测试

API 文档格式

# OpenAPI 3.0 示例
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/api/v1/users:
get:
summary: Get users
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/Pagination'
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: string

API 测试

# Python 单元测试
import unittest
import requests

class TestUserAPI(unittest.TestCase):
BASE_URL = "http://localhost:3000/api/v1"

def test_create_user(self):
data = {
"name": "Test User",
"email": "test@example.com"
}
response = requests.post(f"{self.BASE_URL}/users", json=data)
self.assertEqual(response.status_code, 201)
self.assertIn("id", response.json()["data"])

def test_get_user(self):
response = requests.get(f"{self.BASE_URL}/users/1")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["data"]["id"], 1)

最佳实践总结

  1. 使用名词而非动词作为资源标识
  2. 正确使用 HTTP 方法和状态码
  3. 保持 URI 简洁直观,避免深层嵌套
  4. 提供完整的错误信息和错误代码
  5. 实施适当的缓存策略提高性能
  6. 版本控制确保向后兼容
  7. 编写详细的 API 文档
  8. 实施安全认证和限流

[!tip]

  • 使用 HTTPS 保护所有 API 通信
  • 实施日志记录和监控
  • 保持 API 的一致性和可预测性
  • 定期审查和优化 API 性能

参考资料