REST API 的最佳实践
我们已经介绍了编写 REST API 时的一些最佳实践,例如正确使用 HTTP 方法或为响应选择正确的状态代码。我们还介绍了两种最常用的身份验证系统。但要创建正确的 REST API,还有很多东西需要学习。请记住,REST API 的使用对象是像你这样的开发人员,所以如果你能正确地使用 REST API,让他们的生活更轻松,他们一定会感激不尽。准备好了吗?
端点的一致性
在决定如何给端点命名时,请尽量保持一致。尽管您可以自由选择,但有一套口语规则可以让您的端点更直观、更易懂。让我们列举其中一些:
-
首先,端点应指向特定资源(例如图书或推文),这一点应在端点中明确说明。如果您有一个返回所有图书列表的端点,请不要将其命名为
/library
,因为它的返回内容并不明显。相反,请将其命名为/books
或/books/all
。 -
资源名称可以是复数或单数,但要保持一致。如果有时使用
/books
,有时使用/user
,可能会造成混淆,人们也可能会犯错误。我们个人更喜欢使用复数形式,但这完全取决于你。 -
要检索特定资源时,请尽可能指定 ID。ID 在系统中必须是唯一的,任何其他参数都可能指向两个不同的实体。在资源名称旁边指定 ID,如 /books/249234-234-23-42。
-
如果仅通过 HTTP 方法就能了解端点的功能,就没有必要在端点中添加此信息。例如,如果你想获取一本书或删除一本书,/books/249234-234-23-42 以及 HTTP 方法 GET 和 DELETE 就足够了。如果不明显,可在端点末尾以动词形式说明,如 / employee/9218379182/promote。
尽可能多地记录文档
标题说明了一切。使用 REST API 的人可能不是你,而是其他人。很明显,即使你设计了一套非常直观的端点,开发人员仍然需要了解整套可用端点、每个端点的作用、可用的可选参数等等。
编写尽可能多的文档,并保持更新。多看看其他 API 的文档,收集如何显示信息的想法。有很多模板和工具可以帮助你编写出内容详实的文档,但你必须始终如一、有条不紊地编写文档。开发人员特别讨厌记录任何东西,但当我们需要使用别人的 API 时,我们也喜欢找到清晰美观的文档。
过滤器和分页
应用程序接口(API)的常见用途之一是列出资源并根据某些条件对其进行过滤。我们在创建自己的书店时已经看到过这样一个例子:我们想获取书名或作者中包含特定字符串的图书列表。
一些开发人员试图拥有漂亮的端点,这首先是一件好事。试想一下,如果您只想通过标题进行筛选,您可能会得到一个类似 /books/title/<string> 的端点。我们还可以添加按作者过滤的功能,现在又多了两个端点: /books/title/<string>/author/<string> 和 /books/author/<string>。现在,让我们把描述也加上去—你明白我们要做什么了吗?
尽管有些开发人员不喜欢使用查询字符串作为参数,但这并没有什么不妥。事实上,如果使用得当,端点就会更简洁。你想获取书籍?好吧,那就使用 /books,然后使用查询字符串添加所需的过滤器。
当你有太多相同类型的资源需要一次性获取时,就会出现分页。你应该把分页视为另一个可选的过滤器,指定为 GET 参数。您应该为页面设置默认大小,比如 10 本,但最好让开发人员能够自行定义大小。在这种情况下,开发人员可以指定长度和要检索的页数。
API 版本控制
您的 API 反映了您的应用程序可以执行的操作。 您的代码很可能会不断发展,改进现有功能或添加新功能。 您的 API 也应该更新,公开这些新功能,更新现有端点,甚至删除其中一些端点。
现在想象一下,其他人正在使用您的 REST API,并且他们的整个网站都依赖它。 如果您更改现有端点,他们的网站将停止工作! 他们根本不会高兴,并且会试图寻找其他人可以做你正在做的事情。 这不是一个好的场景,但是那么,如何改进你的 API 呢?
解决方案是使用版本控制。 当您发布新版本的 API 时,不要破坏现有版本; 您应该给用户一些时间来升级他们的集成。 两个不同版本的 API 如何共存? 您已经看到了其中一个选项,即我们推荐您的选项:通过指定用作端点一部分的 API 版本。 您还记得 Twitter API /1.1/statuses/user_timeline.json 的端点吗? 1.1 是指我们要使用的版本。
使用 HTTP 缓存
如果 REST API 的主要特点是大量使用 HTTP,那么为什么不利用 HTTP 缓存呢?不使用 HTTP 缓存确实有其原因,但大多数原因是缺乏正确使用 HTTP 缓存的知识。本书无法解释其实现的每一个细节,但让我们试着对该主题做一个简短的介绍。互联网上的大量资源可以帮助你理解你更感兴趣的部分。
HTTP 响应可分为公共响应和私人响应。公共响应在 API 的所有用户之间共享,而私有响应对每个用户来说都是独一无二的。您可以使用 Cache-Control 标头指定哪种类型的响应,如果请求的方法是 GET,则允许缓存响应。该标头还可以显示缓存的过期时间,也就是说,你可以指定在多长时间内你的响应将保持不变,从而可以被缓存。
其他系统则依赖于生成资源表示的哈希值,并将其添加为 ETag(实体标签)标头,以了解资源是否已更改。与此类似,你也可以设置 Last-Modified 标头,让客户端知道给定资源上次更改的时间。这些系统背后的理念是识别客户端是否已包含有效数据。如果是这样,提供程序将不处理请求,而是返回一个状态代码为 304(未修改)的空响应。当客户端收到该响应时,就会使用其缓存的内容。