API设计
在实现之前设计合约。
何时使用
当用户遇到以下情况时使用:
- 设计新的API或接口;
- 修改现有合约;
- 定义请求/响应模式;
- 审查错误处理、认证、分页或版本控制;
- 与第三方服务集成;
- 询问“这个端点应该是什么样子?”。
1. 明确合约
确定:
- 谁调用API:前端、移动端、服务、合作伙伴、代理;
- 调用者需要完成什么任务;
- 输入和输出的数据;
- 调用者绝对不能看到什么;
- 延迟、容量和可靠性要求;
- 兼容性和版本控制约束。
2. 建模资源和操作
- 对资源使用名词,对非CRUD操作使用显式动作。
- 保持URL稳定且可预测。
- 对于一件事,偏好一种清晰的方式。
- 避免将数据库结构泄露到公共合约中。
- 定义标识符、所有权和租户。
3. 定义模式
对于每个端点或接口:
- 方法和路径;
- 目的;
- 认证和权限;
- 路径、查询和主体参数;
- 验证规则;
- 成功响应;
- 错误响应;
- 幂等性;
- 分页;
- 速率限制;
- 示例。
4. 设计错误
每个错误应包含:
- 稳定的机器可读代码;
- 人性化可读消息;
- 导致错误的字段或参数;
- 用于支持的请求ID;
- 没有堆栈跟踪、机密或内部路径。
使用一致的HTTP状态码。不要为失败操作返回200。
5. 安全与隐私
- 对每个非公共端点进行身份验证。
- 在对象级别授权,而不仅仅是路由级别。
- 在边界验证所有输入。
- 仅返回调用者需要的字段。
- 如果内部ID泄露信息,则不暴露。
- 定义速率限制和滥用控制。
- 将Webhooks视为不受信任的输入。
6. 可演化性
- 添加字段而不是改变其含义。
- 保留旧字段直到客户端迁移。
- 仅在必要时进行版本控制。
- 记录弃用和迁移。
- 避免在次要版本中进行破坏性变更。
7. 输出格式
## 合约
### `METHOD /path`
**目的:** <它的功能>
**认证:** <谁可以调用它>
**幂等性:** <是/否及键>
#### 请求
| 字段 | 类型 | 必填 | 规则 |
|---|---|---|---|
#### 响应
```json
{}
```
#### 错误
| 状态 | 代码 | 何时出现 |
|---|---|---|
#### 示例
```http
METHOD /path
...
```
## 兼容性
- <可以变更的内容>
- <需要新版本的内容>
## 待定问题
- <问题>
规则
- 不要编造业务规则。
- 没有理由就不要暴露内部字段。
- 不要在端点之间使用不一致的命名。
- 不要围绕当前数据库模式设计公共API。
- 不要省略错误和空状态行为。
- 如果API处理金钱、健康或个人数据,则需要安全审查。
质量检查清单
- 调用者和任务明确。
- 模式完整。
- 错误一致且安全。
- 认证和对象级权限已定义。
- 分页和限制已定义。
- 兼容性已处理。
- 示例有效。