目录

RESTful API 最佳实践

REST(Representational State Transfer) 是一种用于设计网络应用程序的架构风格。 它通常用于 Web 服务开发和提供了一种通过 HTTP 协议请求和操作资源的简单方法。

遵循这些约束的 RESTful API 可以更容易地开发和管理。

1. 使用有意义且一致的 URL

使用清晰、简洁的单词来描述您的 API endpoints。使用名词(不是动词),并全部采用小写。

为所访问资源的命名是 RESTful API 最重要的工作之一。使用唯一且有意义的名称至关重要,这些名称需要准确反映正在访问的资源,例如 user/1234product/666。这使用户更容易了解他们正在访问哪些数据,并降低了与其他资源产生冲突的风险。

2. 使用正确的 HTTP 方法

HTTP 请求方法应该用于定义对资源执行的操作。每种方法都有其特定目的,不应相互混用。

GET

从资源中检索数据,例如:

  • 获取员工列表 GET /api/v1/employee?limit=10&offset=0
  • 获取指定员工信息 GET /api/v1/employee/1

POST

创建新资源,例如添加新员工:

1
2
3
4
5
6
7
8
9
curl -X POST \
 -H "Content-Type: application/json" \
 -d '{
 "id": 1,
 "name": "John Doe",
 "email": "[email protected]",
 "department": "Engineering"
}' \
 http://api.example.com/api/employee

PUT

更新现有资源,例如更新员工:

1
2
3
4
5
6
7
8
9
curl -X PUT \
 -H "Content-Type: application/json" \
 -d '{
 "id": 1,
 "name": "Leo Doe",
 "email": "[email protected]",
 "department": "Engineering"
}' \
 http://api.example.com/api/employee/1

PATCH

更新资源的部分信息。它类似于 PUT 方法,但它只更新指定字段,而不是替换整个资源。例如,更新此员工的电子邮件地址,但使所有其他信息保持不变:

1
2
3
4
5
6
curl -X PATCH \
 -H "Content-Type: application/json" \
 -d '{
 "email": "[email protected]"
}' \
 http://api.example.com/api/employee/1

DELETE

删除资源。例如删除员工 DELETE /api/v1/employee/1

HEAD 方法请求一个与 GET 请求相同的响应,但没有响应主体。

以下是如何使用 HEAD 方法的示例:

假设您有一个名为 example.jpg 的文件,它托管在 http://api.example.com/images/example.jpg URL 上的服务器上。现在,假设您想检查此图像文件是否存在以及获取有关它的某些基本信息(例如其大小),而无需下载整个图像数据。要通过 HEAD 请求执行此操作,您需要像这样使用 cURL(命令行 URL 请求):

1
curl -I http://api.example.com/images/example.jpg

在此示例中,-I 选项告诉 cURL 只在其响应中显示 HTTP 头部信息。这将有效地阻止 cURL 下载图像文件的实际内容,而是向您提供有关它的必要元数据(例如其 Content-Type、Content-Length 等)。

以下是输出可能是什么样子的示例:

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: nginx/1.16.1
Date: Mon, 25 Jan 2021 13:49:55 GMT
Content-Type: image/jpeg
Content-Length: 5857
Last-Modified: Mon, 25 Jan 2021 13:49:36 GMT
Connection: keep-alive
ETag: "5f9c5c3-17a5"
Accept-Ranges: bytes

在此输出中,您可以看到 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. 验证输入并妥善处理错误

输入验证对于防止恶意攻击或意外数据操作至关重要。在处理用户输入之前始终对其进行验证。如果出现任何错误,请提供有意义的错误消息以帮助有效地解决问题。

  • 验证:检查请求主体中是否存在必需字段,并确保其值符合特定条件(例如电子邮件格式)。
  • 错误处理:捕获异常并返回带有错误发生原因的清晰描述的适当错误响应。
1
2
3
4
{
  "code": 666,
  "message": "在处理您的请求时出错。"
}

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 请求配合使用的示例:

1
2
3
4
GET /api/employee/1 HTTP/1.1
Host: api.example.com
Accept: application/json
If-Match: "e9c56f7d2324f08a941b26b9e3e9bf"

在此示例中,客户端仅在该员工的 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,从而为你的用户提供出色的体验。