对于那些试图完善 API 策略的团队来说,良好的 API 设计是一个经常出现的话题。 在上一篇博客文章中,我简要讨论了 API 设计的重要性。精心设计的 API 的好处包括:改善开发者体验、加快文档编写以及提高 API 的采用率。 但到底什么才是良好的 API 设计?在这篇博客文章中,我将详细介绍设计 RESTful API 的一些最佳实践。
精心设计的 API 的特征
总的来说,有效的 API 设计将具有以下特征
- 易于阅读和使用:精心设计的 API 将易于使用,并且其资源和相关操作可以被经常使用它的开发人员快速记住。
- 难以误用:实现和集成设计良好的 API 将是一个简单的过程,并且编写不正确的代码的可能性会降低。它具有信息丰富的反馈,并且不会对 API 的最终消费者强制执行严格的准则。
- 完整且简洁:最后,一个完整的 API 将使开发人员能够针对您公开的数据制作全面的应用程序。完整性通常会随着时间的推移而实现,大多数 API 设计人员和开发人员都会在现有 API 的基础上逐步构建。这是每个拥有 API 的工程师或公司都必须努力实现的目标。
为了说明下面列出的概念,我将以一个照片分享应用程序为例。该应用程序允许用户上传照片,并使用照片拍摄地点和描述与它们相关的情绪的标签对其进行表征。
集合、资源及其 URL
了解资源和集合
资源是 REST 概念的基础。资源是一个足够重要可以自身引用的对象。资源具有数据、与其他资源的关系以及对其进行操作以允许访问和操作相关信息的方法。 一组资源称为集合。集合和资源的内容取决于您的组织和消费者要求。例如,如果您认为市场将从获取有关您产品用户群的基本信息中获益,那么您可以将其作为集合或资源公开。 统一资源定位符 (URL) 标识资源的在线位置。此 URL 指向 API 资源存在的位置。基本 URL 是此位置的一致部分。 在照片共享应用程序的情况下,我们可以通过集合和资源公开有关使用该应用程序的用户的数据,并通过适当的 URL 访问这些数据。
- /users:用户集合
- /users/username1:包含有关特定用户信息的资源
名词更好地描述 URL
基本 URL 应该简洁、优雅且简单,以便使用您产品的开发人员可以在其 Web 应用程序中轻松使用它们。长而难以阅读的基本 URL 不仅看起来很糟糕,而且在尝试重新编码时也容易出错。应该始终信任名词。 虽然建议保持集合为复数形式,但关于资源名词使用单数还是复数形式没有规则。为了保持一致性,在所有资源和集合中分别保持相同的复数形式是一个很好的做法。 保持这些名词具有自我解释性有助于开发人员从 URL 中了解所描述的资源类型,这最终可以使他们在使用您的 API 时能够自给自足。 回到照片共享应用程序,假设它有一个公共 API,其中 /users 和 /photos 作为集合。请注意它们都是复数名词吗?它们也具有自我解释性,我们可以推断出 /users 和 /photos 分别提供了有关产品注册用户群和共享照片的信息。
使用 HTTP 方法描述资源功能
所有资源都有一组可以对其进行操作的方法,以处理 API 公开的数据。 RESTful API 主要由 HTTP 方法组成,这些方法对任何资源都有明确且独特的操作。以下是 RESTful API 中用于定义任何资源或集合的 CRUD 操作的常用 HTTP 方法列表。
方法 |
描述 |
GET |
用于检索资源的表示。 |
POST |
用于创建新的资源和子资源 |
PUT |
用于更新现有资源 |
PATCH |
用于更新现有资源 |
DELETE |
用于删除现有资源 |
(如果您想知道 PUT 和 PATCH 之间的区别,请查看 StackOverflow 上的此帖子。) 将动词排除在 URL 之外也是一个好主意。操作 GET、PUT、POST 和 DELETE 已经用于操作由 URL 描述的资源,因此在 URL 中使用动词而不是名词会使您在使用资源时感到困惑。 在照片共享应用程序中,以 /users 和 /photos 作为端点,您的 API 的最终消费者可以使用上述 RESTful CRUD 操作轻松直观地使用它们。
响应
提供反馈以帮助开发者成功
向开发者提供有关他们如何使用您的产品的良好反馈对于提高采用率和留存率大有裨益。 每个客户端请求和服务器端响应都是一条消息,在理想的 RESTful 生态系统中,这些消息必须是自我描述的。 良好的反馈包括对正确实现的积极验证,以及对不正确实现的信息性错误,这可以帮助用户调试和纠正他们使用产品的方式。对于 API 而言,错误是提供 API 使用上下文的好方法。 将您的错误与标准 HTTP 代码对齐。不正确的客户端调用应具有与其关联的 400 类型错误。如果有任何服务器端错误,则必须将合适的 500 响应与其关联。针对您的资源使用的成功方法应返回 200 类型响应。 有很多响应代码。有关更多信息,请查看此 REST API 教程。 一般来说,使用您的 API 时有三种可能的结果:-
- 客户端应用程序的行为错误(客户端错误 - 4xx 响应代码)
- API 的行为错误(服务器错误 - 5xx 响应代码)
- 客户端和 API 均工作正常(成功 - 2xx 响应代码)
当最终用户在使用您的 API 时遇到障碍时,帮助他们取得成功对于改善开发者体验和防止 API 误用至关重要。请清楚地描述这些错误响应,但要保持简洁明了。在错误代码中提供足够的信息,以便最终用户可以开始解决问题,如果您觉得需要更多信息,请提供指向其他文档的链接。
为您的所有 GET 响应提供示例
设计良好的 API 还应包含成功调用 URL 后可以预期的响应示例。此示例响应应简单、清晰且易于理解。一个好的经验法则是帮助开发人员在五秒钟内准确了解成功响应会给他们带来什么。 回到我们的照片分享应用程序,我们定义了 /users 和 /photos URL。/users 集合将以数组形式提供所有已向应用程序注册的用户的用户名和加入日期。 您可以使用 API 设计工具,按照以下方式在 Swagger (OpenAPI) 规范中定义您的 API:
- responses:
- 200:
- description: 成功返回有关用户的信息
- schema:
- type: array
- items:
- type: object
- properties:
- username:
- type: "string"
- example: "kesh92"
- created_time:
- type: "dateTime"
- example: "2010-01-12T05:23:19+0000"
请注意,每个响应项中都描述了数据类型和最终用户可以从成功的 GET 调用中获得的示例。最终用户将在 JSON 中收到的成功响应如下所示。
- {
- “data”:[
- {
- “Username”:“example_user1”,
- “created_time":“2013-12-23T05:51:14+0000 ”
- },
- {
- “username”:“example_user2”,
- “created_time":“2015-3-19T17:51:15+0000 ”
- }
- ……
- ]
- }
如果最终用户使用 GET 方法成功调用端点,则用户应获得上述数据以及 200 响应代码,以验证其使用是否正确。同样,不正确的调用应生成适当的 400 或 500 响应代码,并提供相关信息以帮助用户更好地操作集合。
请求
优雅地处理复杂性
您尝试公开的数据可以由许多属性来表征,这些属性对于使用您的 API 的最终用户可能是有益的。这些属性描述了基本资源,并隔离了可以通过适当方法操作的特定信息资产。 API 应力求完整,并提供所有必需的信息、数据和资源,以帮助开发人员以无缝方式进行集成。 但完整性意味着要考虑到 API 的常见用例。可能存在许多此类关系和属性,为每个关系和属性都定义资源并不是一个好习惯。 还应考虑资源公开的数据量。如果您尝试公开大量数据,可能会对服务器产生负面影响,尤其是在负载和性能方面。 上述情况和关系在 API 设计中是重要的考虑因素,可以使用适当的参数来处理。您可以使用查询参数中的“?”来扫描属性和限制响应,或者使用路径参数来隔离客户端正在处理的特定数据组件。 让我们以我们的照片分享应用程序为例。 对于开发人员来说,获取有关在特定位置和特定主题标签中共享的所有照片的信息可能很有用。您还希望将每次 API 调用的结果数量限制为 10 个,以防止服务器负载过高。如果最终用户想要查找波士顿所有带有主题标签 #winter 的照片,则调用将是:
- GET /photos?location=boston&hashtag=winter&limit=10
请注意,复杂性现在已简化为与查询参数的简单关联。如果您想根据客户端的请求提供有关特定用户的信息,则调用将是:
- GET /users/kesh92
其中 kesh92 是 users 集合中特定用户的用户名,它将返回 kesh92 的位置和加入日期。 这些只是您设计参数的一些方法,这些参数力求实现 API 的完整性,并帮助您的最终开发人员直观地使用您的 API。 最后,当您有疑问时,请将其删除。如果您对特定资源或集合的功能有任何疑虑,请将其留到下一次迭代。开发和维护 API 是一个持续的过程,等待来自正确用户的反馈对于构建一个强大的 API 大有帮助,该 API 使能够用户以创造性的方式集成和开发应用程序。
开始 API 设计
没有一种 API 设计方法适用于每个组织。以上建议只是建议—可以根据您的用例和需求使用或放弃的建议。 API 设计至关重要的主要原因之一是帮助最终用户使用您的 API。他们的需求应该是指引您设计和构建优秀 API 的方向。
有兴趣开始 REST API 的 API 设计吗? 了解 Swagger API 设计工具如何提供帮助。