RESTful API 最佳实践
REST(Representational State Transfer) 是一种用于设计网络应用程序的架构风格。 它通常用于 Web 服务开发和提供了一种通过 HTTP 协议请求和操作资源的简单方法。
遵循这些约束的 RESTful API 可以更容易地开发和管理。
1. 使用有意义且一致的 URL
使用清晰、简洁的单词来描述您的 API endpoints。使用名词(不是动词),并全部采用小写。
为所访问资源的命名是 RESTful API 最重要的工作之一。使用唯一且有意义的名称至关重要,这些名称需要准确反映正在访问的资源,例如 user/1234
或 product/666
。这使用户更容易了解他们正在访问哪些数据,并降低了与其他资源产生冲突的风险。
2. 使用正确的 HTTP 方法
HTTP 请求方法应该用于定义对资源执行的操作。每种方法都有其特定目的,不应相互混用。
GET
从资源中检索数据,例如:
- 获取员工列表
GET /api/v1/employee?limit=10&offset=0
。 - 获取指定员工信息
GET /api/v1/employee/1
。
POST
创建新资源,例如添加新员工:
|
|
PUT
更新现有资源,例如更新员工:
|
|
PATCH
更新资源的部分信息。它类似于 PUT 方法,但它只更新指定字段,而不是替换整个资源。例如,更新此员工的电子邮件地址,但使所有其他信息保持不变:
|
|
DELETE
删除资源。例如删除员工 DELETE /api/v1/employee/1
。
HEAD
HEAD
方法请求一个与 GET 请求相同的响应,但没有响应主体。
以下是如何使用 HEAD 方法的示例:
假设您有一个名为 example.jpg
的文件,它托管在 http://api.example.com/images/example.jpg
URL 上的服务器上。现在,假设您想检查此图像文件是否存在以及获取有关它的某些基本信息(例如其大小),而无需下载整个图像数据。要通过 HEAD 请求执行此操作,您需要像这样使用 cURL(命令行 URL 请求):
|
|
在此示例中,-I
选项告诉 cURL 只在其响应中显示 HTTP 头部信息。这将有效地阻止 cURL 下载图像文件的实际内容,而是向您提供有关它的必要元数据(例如其 Content-Type、Content-Length 等)。
以下是输出可能是什么样子的示例:
|
|
在此输出中,您可以看到 HEAD 请求返回了 200 OK 状态代码,表示图像文件存在并且可以访问。此外,它还提供了有关内容类型(image/jpeg)、内容长度(5857 字节)、上次修改日期、ETag 等的信息。
通过使用 HEAD 方法,您可以在不消耗不必要带宽的情况下有效地检索 RESTful API 中的资源元数据,而无需下载其全部内容。
OPTIONS
OPTIONS 方法描述目标资源的通信选项。
TRACE
TRACE
方法沿着到目标资源的路径执行消息环回测试。
3. 返回合适的 HTTP 状态码
HTTP 状态码 提供有关请求结果的宝贵信息。使用它们来传达您的 API 调用的成功或失败。
1xx 信息响应
- 100 继续
- 101 切换协议
- 102 处理
2xx 成功响应
- 200 正确
- 201 已创建
- 202 已接受
- 203 非权威信息
- 204 无内容
- 205 重置内容
- 206 部分内容
- 207 多状态
- 208 已报告
- 226 IM 使用
3xx 重定向消息
- 300 多项选择
- 301 永久移动
- 302 找到
- 303 查看其他
- 304 未修改
- 307 临时重定向
- 308 永久重定向
4xx 客户端错误响应
- 400 错误请求
- 401 未授权
- 402 需要付费
- 403 禁止
- 404 未找到
- 405 方法不被允许
- 406 不可接受
- 407 需要代理身份验证
- 408 请求超时
- 409 冲突
- 410 已消失
- 411 长度要求
- 412 前提条件失败
- 413 载荷太大
- 414 URI 太长
- 415 不支持的媒体类型
- 416 范围无法满足
- 417 期望失败
- 418 我是茶壶
- 422 不可处理的实体
- 423 已锁定
- 424 依赖项失败
- 426 需要升级
- 428 需要前提条件
- 429 请求过多
- 431 请求头字段太大
- 451 因法律原因不可用
5xx 服务器错误响应
- 500 内部服务器错误
- 501 未实现
- 502 错误的网关
- 503 服务不可用
- 504 网关超时
- 505 HTTP 版本不受支持
- 506 变体也协商
- 507 存储空间不足
- 508 检测到循环
- 510 未扩展
- 511 需要网络身份验证
4. 验证输入并妥善处理错误
输入验证对于防止恶意攻击或意外数据操作至关重要。在处理用户输入之前始终对其进行验证。如果出现任何错误,请提供有意义的错误消息以帮助有效地解决问题。
- 验证:检查请求主体中是否存在必需字段,并确保其值符合特定条件(例如电子邮件格式)。
- 错误处理:捕获异常并返回带有错误发生原因的清晰描述的适当错误响应。
|
|
5. 针对大型数据集使用分页
通过将大量数据分成更小、更易于管理的块,分页有助于管理大量数据。这提高了性能并减少了通过网络传输的信息量。
- 在您的 API 中实现
?limit=10&offset=0
以限制返回的记录数(例如 10)并为这些记录设置起始点(例如记录 0)。
6. 启用缓存以提高性能
缓存通过存储先前调用的响应来减少对您的 API 发出的请求数。这提高了性能并降低了服务器负载。
- 在您的响应中设置适当的缓存头(例如
Cache-Control: max-age=600, public
)。这会在支持缓存的客户端上将响应缓存 10 分钟(600 秒)。
7. API 版本控制
版本控制允许你在更改 API 的同时保持向后兼容性。这可确保现有客户端在添加新功能或引入重大更改后仍能继续工作。
- 在 URL 中包含 API 版本(例如,“/api/v1/employee”)。
- 同时支持多个版本,以便客户端可以按自己的速度进行升级。
8. 使用 JSON 进行数据交换
JSON(JavaScript 对象表示法)是一种轻量且易于解析的格式,适用于 RESTful API。大多数编程语言都广泛支持它,与 XML 相比,它的开销也较低。
- 获取资源时返回 JSON 数据(例如,“{“id”: 1,“name”: “John Doe”}”)。
9. 保护你的 API
- 使用 OAuth、JWT 等身份验证机制。
- 使用 HTTPS。
- 使用速率限制以防止滥用。
10. 使用 If-Match 和 ETags Header 进行并发控制
ETag(实体标记)是 RESTful API 中分配给资源的唯一标识符。它有助于客户端识别自上次请求后资源是否已更改,这对于 PUT 或 DELETE 等条件请求很有用。
要在 GET 请求中使用 ETag,你应该在 HTTP 请求中包含“If-Match”头。这会通知服务器,只有当资源的 ETag 与头中提供的值匹配时,你才希望检索该资源。如果自上次请求后该资源已更改,则服务器将返回 412 预处理失败响应,而不是请求的数据。
以下是如何将“If-Match”与 GET 请求配合使用的示例:
|
|
在此示例中,客户端仅在该员工的 ETag 与值“e9c56f7d2324f08a941b26b9e3e9bf”匹配时才请求 ID 为 1 的员工。如果自上次请求后资源已修改(即其 ETag 不再与所提供的值匹配),则服务器将响应 412 预处理失败状态代码,并且不会返回请求的数据。
当多个客户端尝试同时更新同一资源时,此技术有助于防止出现竞争条件。通过在执行更新之前检查 ETag,你可以确保你的更改不会覆盖在此期间其他客户端所做的更改。
11. 编写 API 文档
API 文档对于帮助开发人员理解如何有效使用 RESTful API 非常重要。
使用 OpenAPI 规范(Swagger)
OpenAPI 规范是描述 REST API 的广泛采用的标准。通过使用此格式,你可以生成可供机器读取且对人友好的文档,其中包括有关 API 资源、端点、HTTP 方法、请求参数、响应数据结构等的详细信息。
组织你的文档
将你的 API 文档组织成概述、身份验证、资源、端点等逻辑部分,以便开发人员能够快速找到所需的信息。
从 OpenAPI 文档自动生成代码
OpenAPI Generator 允许自动生成 API 客户端库(SDK 生成)、服务器存根、文档和配置,前提是给定 OpenAPI 规范(v2、v3)。
12. 持续监控和改进 API
最后,随着时间的推移,持续监控和改进 RESTful API 非常重要。使用合适的监控工具(例如指标或日志分析)来识别需要改进的领域,并相应地进行更改。这有助于确保 API 随着时间的推移保持可扩展性、安全性以及易用性。
通过遵循这些最佳实践,你可以创建更加高效、可靠且可维护的 RESTful API,从而为你的用户提供出色的体验。