Skip to content

RESTful API 规范

核心原则

RESTful API 必须遵循 REST 架构风格,使用标准 HTTP 方法和状态码,确保 API 的可预测性和一致性。

允许的做法

URL 设计

  • 使用 名词复数形式表示资源
  • 使用 kebab-case(短横线)命名
  • 使用 嵌套表示资源关系(不超过 2 层)
✅ 正确
GET    /api/users              # 获取用户列表
GET    /api/users/{id}         # 获取单个用户
GET    /api/users/{id}/orders  # 获取用户的订单
POST   /api/products           # 创建商品

HTTP 方法

  • 使用 标准 HTTP 方法表示操作
方法用途示例
GET获取资源GET /api/users
POST创建资源POST /api/users
PUT完整更新资源PUT /api/users/
PATCH部分更新资源PATCH /api/users/
DELETE删除资源DELETE /api/users/
✅ 正确示例

# 用户管理
GET    /api/users          # 获取用户列表
POST   /api/users          # 创建用户
GET    /api/users/{id}     # 获取用户详情
PUT    /api/users/{id}     # 更新用户(全量)
PATCH  /api/users/{id}     # 更新用户(部分)
DELETE /api/users/{id}     # 删除用户

# 商品管理
GET    /api/products       # 获取商品列表
POST   /api/products       # 创建商品
GET    /api/products/{id}  # 获取商品详情

HTTP 状态码

  • 使用 标准 HTTP 状态码
状态码说明使用场景
200OK成功获取/更新资源
201Created成功创建资源
204No Content成功删除资源
400Bad Request请求参数错误
401Unauthorized未认证
403Forbidden无权限
404Not Found资源不存在
500Internal Server Error服务器错误
go
// ✅ 正确 - Echo 框架示例
func GetUser(c echo.Context) error {
    id := c.Param("id")
    user, err := userService.GetByID(id)
    if err != nil {
        return c.JSON(http.StatusNotFound, response.Fail(404, "用户不存在"))
    }
    return c.JSON(http.StatusOK, response.Success(user))
}

func CreateUser(c echo.Context) error {
    var req CreateUserRequest
    if err := c.Bind(&req); err != nil {
        return c.JSON(http.StatusBadRequest, response.Fail(400, "参数错误"))
    }
    user, err := userService.Create(&req)
    if err != nil {
        return c.JSON(http.StatusInternalServerError, response.Fail(500, "创建失败"))
    }
    return c.JSON(http.StatusCreated, response.Success(user))
}

查询参数

  • 使用 查询参数进行过滤、排序、分页
✅ 正确

# 分页
GET /api/users?page=1&pageSize=20

# 过滤
GET /api/products?status=active&category=electronics

# 排序
GET /api/users?sort=createdAt&order=desc

# 搜索
GET /api/users?q=alice

# 字段选择
GET /api/users?fields=id,name,email

版本控制

  • 使用 URL 路径版本控制
  • 使用 v1, v2 格式
✅ 正确
GET /api/v1/users
GET /api/v2/users

禁止的做法

禁止的 URL 设计

  • 禁止 使用动词(除非是 RPC 风格的操作)
  • 禁止 使用下划线
  • 禁止 URL 结尾斜杠
❌ 错误
GET /api/getUsers           # 使用动词
GET /api/user_list          # 使用下划线
GET /api/users/             # 结尾斜杠
GET /api/users/1/orders/2/items/3  # 嵌套过深

禁止的操作

  • 禁止 使用 GET 方法修改数据
  • 禁止 在 URL 中包含敏感信息
  • 避免 返回不一致的数据结构
❌ 错误
GET /api/users/delete/{id}           # GET 不应修改数据
GET /api/users?password=secret       # URL 包含敏感信息

RESTful API 设计示例

用户管理 API

# 用户列表(分页)
GET /api/v1/users?page=1&pageSize=20
Response: {
  "success": true,
  "data": [...],
  "total": 100,
  "current": 1,
  "pageSize": 20
}

# 创建用户
POST /api/v1/users
Request: {
  "name": "Alice",
  "email": "alice@example.com"
}
Response: {
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com"
  }
}

# 获取用户详情
GET /api/v1/users/123
Response: {
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice",
    "email": "alice@example.com"
  }
}

# 更新用户(部分)
PATCH /api/v1/users/123
Request: {
  "name": "Alice Wang"
}
Response: {
  "success": true,
  "data": {
    "id": 123,
    "name": "Alice Wang",
    "email": "alice@example.com"
  }
}

# 删除用户
DELETE /api/v1/users/123
Response: {
  "success": true
}

资源关系 API

# 获取用户的订单
GET /api/v1/users/123/orders

# 获取订单详情(推荐使用独立端点)
GET /api/v1/orders/456

# 创建用户的订单
POST /api/v1/users/123/orders

特殊操作

非 CRUD 操作

对于不符合 CRUD 的操作,使用 动词子资源:

✅ 正确

POST /api/v1/users/123/activate        # 激活用户
POST /api/v1/orders/456/cancel         # 取消订单
POST /api/v1/orders/456/refund         # 退款
POST /api/v1/users/123/reset-password  # 重置密码
POST /api/v1/documents/123/submit      # 提交文档
POST /api/v1/tasks/456/assign          # 分配任务
POST /api/v1/tasks/456/complete        # 完成任务

实现示例

go
// ✅ 正确 - Echo 框架实现
func (h *TaskHandler) AssignTask(c echo.Context) error {
    taskID := c.Param("id")
    var req AssignTaskRequest
    if err := c.Bind(&req); err != nil {
        return c.JSON(http.StatusBadRequest, response.Fail(1000, "参数错误"))
    }

    err := h.taskService.Assign(c.Request().Context(), taskID, req.TranslatorID)
    if err != nil {
        return c.JSON(http.StatusInternalServerError, response.Fail(500, "分配失败"))
    }

    return c.JSON(http.StatusOK, response.Success(nil))
}

批量操作

✅ 正确

POST /api/v1/users/batch-delete
Request: {
  "ids": [1, 2, 3]
}

POST /api/v1/products/batch-update
Request: {
  "ids": [1, 2, 3],
  "status": "inactive"
}

自定义操作最佳实践

原则 1:优先考虑标准 REST 方法

go
// ✅ 优先使用 PATCH 更新状态
PATCH /api/v1/orders/123
Request: { "status": "cancelled" }

// ⚠️ 仅在业务语义复杂时使用自定义操作
POST /api/v1/orders/123/cancel
Request: { "reason": "customer request", "refund": true }

原则 2:自定义操作应使用 POST 方法

✅ 正确 - 使用 POST 执行操作
POST /api/v1/users/123/activate
POST /api/v1/orders/456/ship

❌ 错误 - 不要使用 GET执行修改操作
GET /api/v1/users/123/activate

原则 3:操作名称使用动词

✅ 正确
POST /api/v1/tasks/123/submit
POST /api/v1/documents/123/approve
POST /api/v1/users/123/reset-password

❌ 错误
POST /api/v1/tasks/123/submission
POST /api/v1/documents/123/approval

常见自定义操作场景

状态转换操作

go
// 订单状态转换
POST /api/v1/orders/123/cancel      // 取消订单
POST /api/v1/orders/123/ship        // 发货
POST /api/v1/orders/123/complete    // 完成订单

// 用户状态管理
POST /api/v1/users/123/activate     // 激活
POST /api/v1/users/123/deactivate   // 停用
POST /api/v1/users/123/lock         // 锁定

批准/审核操作

go
POST /api/v1/documents/123/submit   // 提交审核
POST /api/v1/documents/123/approve  // 批准
POST /api/v1/documents/123/reject   // 拒绝

Request: {
  "comment": "审核意见"
}

分配/转移操作

go
POST /api/v1/tasks/123/assign       // 分配任务
Request: {
  "assigneeId": 456
}

POST /api/v1/tickets/123/transfer   // 转移工单
Request: {
  "targetUserId": 789,
  "note": "转移原因"
}

导出/生成操作

go
POST /api/v1/reports/generate       // 生成报告
Request: {
  "startDate": "2025-01-01",
  "endDate": "2025-01-31",
  "format": "pdf"
}

Response: {
  "success": true,
  "data": {
    "reportId": "abc123",
    "downloadUrl": "https://cdn.example.com/reports/abc123.pdf"
  }
}

相关文档