本文来自REST API Development tips and best practices — Part 1
这是有关REST API的三篇文章系列中的第一篇。
- 第1部分:简介和规划
- 第2部分:架构建议,常见错误和不建议使用
- 第3部分:文档提示和超越基础知识
介绍
如今,REST API无处不在。如果您正在开发支持网络的应用程序,则很可能您已经在代码中写了至少一行代码,并且很有可能正在阅读本文,因为您将要编写自己的代码。
本篇文章的内容
本系列文章不是REST的简介。它假定您对REST是什么以及它要实现的目标有清楚的了解。也绝不是有关Web API设计和开发的全面的最佳实践文章。网上已经有很多这样的书,我建议您阅读尽可能多的书。
最主要的是,本篇文章列出了人们在设计和实现REST API时常犯的,经常被忽略的错误。我知道,不仅是因为我在其他人的API中遇到了它们,而且还因为我自己做了其中一些。 :)
为什么这样写
在理想环境中,开发REST API之后,所有人要做的第一件事就是为其编写客户端应用程序。没有什么比让您自己真正地使用它来揭示您创作的低效率了。我知道这一点,因为我不得不做很多次。
当然,我们的世界并不完美,在大多数情况下,后端开发人员必须在完成API实施后继续进行其他工作,但是直到API调用者必须找到他并让他解释代码。我也曾多次处于这个不愉快的位置,所以希望我的错误和提示可以帮助您节省时间 - 以便您无需再添加新功能之前还要回头调整以前的API代码。
规划
1.开始之前
学习尽可能多的REST API设计和开发文档和书籍!在这里,我不会提及常见的提示,例如使用名词而不是动词URI(糟糕,我只是…)等等,但这是因为我认为您已经在其他地方阅读过它们。
考虑替代方案
REST作为范例非常流行,但是它有很多风格。在继续进行任何操作之前,应尽可能多地研究一下它们。当您使用它时,别忘了检查GraphQL —一种完全不同的方法,这种方法不仅在某些用例中看起来很棒,而且还被Facebook(开发者)和GitHub的新v4 API所使用。
看看别人做了什么
查看并实际尝试使用信誉良好的组织中尽可能多的流行API。以下是一些入门指南:GitHub,Stripe,Twitter,PayPal
2.基础
不要以为您的API会变小-几乎不会发生。即使您是唯一将其用于自己的客户端应用程序的人,很快您将需要额外的接口,分页,分析,测试模式等等谁也不知道的功能,而这甚至是在您的应用程序流行和其他人开始之前正在请求访问您的API ...
好吧-也许这很麻烦;但是通常在软件开发中会遇到这种情况,如果您不及早奠定坚实的基础,从长远来看,您将为此付出高昂的代价。由于API需要保持一致以便易于使用,因此尝试使用胶带将功能添加到API中不仅会给您带来麻烦,而且也会给您的客户带来麻烦。
此外,您越能保持事物整洁,完成它们所花费的时间就越少,并且很快就会…
3.规格
谈论坚实的基础;在实际开始编写代码之前,请尝试为您的API创建规范。我知道,如果您以前没有做过,那听起来很无聊,但是从长远来看,它会带来回报,并为您节省大量时间和麻烦。
随着越来越多的组织和替代方案在此方面融合,OpenAPI规范(OAS-以前为Swagger)似乎是目前最受欢迎的方法。另外,Postman是一个很棒的API开发环境,但仅对个人或小型开发人员团队免费。
我强烈建议不要忽略此技巧,除非您正在开发仅会消耗的小型内部API。
4.版本控制
我不会在本文中重点介绍不同的版本控制方法,因为有关此主题的在线资源很多。我只想强调一下,选择可靠的版本控制方法并认真遵循它是多么重要。我还将介绍一种多年来一直为我服务的方法。
为什么重要
强大的版本控制方法使您的消费者(以及终端用户)安心,因为它可以防止API的更改干扰到现有客户端。即使客户端应用程序和API是由相同的开发人员或一个组织来开发的。在许多情况下,在API更新时仍可能使用了废弃的版本。
这种现象最常见的情况是移动或桌面OS客户端应用程序,开发人员很少能完全控制更新周期。无论您的客户端更新机制有多么出色和自动化,您几乎都不可能百分百确定您的用户用的是最新版本的客户端。
对于默认情况下启用的应用程序,iOS具有非常可靠的自动更新机制,但是根据用户的喜好和网络状态,其设备可能没有机会在下次运行时更新客户端应用程序。较新的Android版本也是如此,而较旧的版本在应用程序更新中仍有可能在使用。
另一方面,桌面应用程序可能会也可能不会提供自动更新机制-但大多数情况下会选择启用这些机制,并且在某些情况下(例如企业环境)始终不允许即时更新。甚至浏览器客户端应用程序也可能(在大多数情况下应该)与后端分离,因此发布周期与API完全不同。
告诉使用者变更的信息
即使您拥有具有最佳版本控制系统的完美API,但如果您的消费者没有意识到它丰富的功能,那么这一切都将毫无意义。传达变更和新功能对于用户充分利用它们至关重要。更重要的是,尽早警告用户有关将要弃用旧的版本,以便他们有足够的时间来更新,测试和发布新版本。
保持最新文档并发布每个版本的详细变更日志至关重要,这应该是您开发周期的一部分。
主要/次要版本方法
多年来,我一直很欣赏的版本控制方法是主要/次要版本计划。您的API具有一个主要版本号(仅在发生重大更改时才更新)(如果操作正确),而一个次要版本号则在有少量增量添加时随时更新。
从另一个角度看,每个主要版本都保证API资源和架构的结构在其生命周期内不会中断,无论同时发布了多少个次要版本。次要版本应该向后兼容。
主版本通常是API基本网址的一部分(例如https://xxx/v1/endpoint),次版本可以通过请求标头进行选择。如果未提供请求标头,则使用最新的次要版本。有许多流行的API都遵循这种方法,我最喜欢的一个是Stripe(使用次要版本的发布日期)。
在以下各节中,我将在谈论API更新时再次提及这种方法,但您可以自行选择最适合自己要求的正式版本控制系统。只要记住,一旦您这样做,就必须专注它。
5.测试
通常,作为软件开发过程不可或缺的一部分,测试对于您的API是必不可少的。由于API通常充当服务器和一个或多个客户端应用程序之间建立链接,因此它们必须在所有情况下都可靠,并且不能承受任何形式的中断。此外,由于它们通常都暴露在网络中,因此容易遭受大量风险,因此必须对它们进行大量常见且不太常见的场景的彻底测试。
通过使用Swagger,Postman或REST控制台之类的工具进行手动测试,仅能在开发的最初阶段提供帮助。从一开始就维护一套自动化测试,就可以使最终产品的质量与众不同。
由于其性质,API是功能测试的理想选择。对它们的内部实现进行单元测试非常重要(就像对其他任何软件一样),但是在我看来,对API进行功能测试虽然花费了很多间,但它能提供更多的价值。
维护一个可以在测试过程中设置和删除的测试数据库是该过程的重要部分。向数据库添加导致错误问题的数据(在开发过程中观察到或由用户报告),并使用回归测试套件,来确保您彻底摆脱了这些错误。
即使在测试了到了最后情况之前,也不要假设输入参数的验证是完整的(不要忘记您的客户端应用程序本身可能有很多bug)。最后,将时间投入到适当的日志记录基础结构中,以捕获剩余的少量运行时错误,观察使用者的行为并使用该信息创建更多的测试方案。
6.部署
您可能已经注意到(或者您将继续阅读时会注意到)一样,这篇文章主要集中在如何创建不会破坏事物的API上。当然,在所有软件产品中最可怕的阶段是部署。
在大多数情况下,如果您正确地进行了测试和版本控制,则在部署过程中遇到问题的机会非常低;但是,这里有一些提示可能会有所帮助。
解耦一切
这是一个非常常见的情况:
您的API向外部的几个B2B客户端提供数据,也为您自己的组织开发的几个移动客户端和Web应用提供数据。为了容易管理,API 可以通过Web访问。
这意味着,当需要更新服务器应用程序时,如果出现故障,则很有可能API也将中断。如果发生这种情况,该API将会损害到所有消费者的利益,最终用户会怪到公司的头上。
在这种情况下,紧密耦合的另一个缺陷是一个应用程序的发布周期会影响所有其他应用程序。这将需要复杂的计划和编排流程。此外,从业务角度看,这没有任何意义(每个应用程序都应在不影响其他应用程序的情况下发布)。
如果您的API和其他应用程序是作为基础结构的独立模块开发的,那么所有这些都将消失。有人可能会争辩说拥有更多单独的模块意味着更多的故障点,但是可以通过适当的版本控制和测试来解决。此外,即使您的API的新版本在部署时确实中断了,您的团队也将第一个知道。在这种情况下,如果没有更好的办法,您总是可以将应用的发布推迟几天,直到您确定一切正常为止。
您必须通过严格的测试来防范的另一种危险情况是,新版本的服务器应用程序破坏了API的现有版本。所以,避免这种情况的唯一方法(当然)是通过严格的开发过程以及正确的版本控制和测试。将基础架构的所有部分分为不同的模块会进一步鼓励使用这种方法。
7.弃用
随着您的应用程序的不断完善,您将不可避免地弃用旧的API版本,从而李艾使用一个新的API。仍在开发中的客户端应用程序也必须升级到新版本,但这可能需要一些时间。
而且,在某些情况下,即使开发人员立即采取行动也并不意味着立即对客户端应用程序进行更新。尽管可以在最终用户发布后立即提供更新版本的Web应用程序,但较早版本的移动和本机OS应用程序倾向于保留很长时间。有些用户并不真正了解(或什至不知道)手机或计算机上应用程序的更新过程。如果这些应用突然开始出现故障,则用户的回馈可能就是停止使用它们。
弃用主要API版本并不意味着服务中断。已弃用的版本应继续按原样继续工作一段时间(尽可能长的时间),并将清楚明确,重复地(接近结束)传达给您的消费者。理想情况下,您的API的较早版本永远都不应停止工作,除非它们构成安全风险或对后端造成损害。
8.经常被忽略的良好做法
您可以对资源使用复数形式或单数形式,但不能同时使用
/cars 很好,/car 也可以,但是您不能同时使用两者。选择一种形式,并在整个API中坚持使用。如果您不这样做,将来会使接替自己的开发人员甚至自己感到困惑。
在PUT和PATCH响应中返回更新的对象
通过PUT或PATCH动词成功请求后,客户端通常需要知道更新后的状态。由于很可能同时有多个客户端更新它,因此这是使每个人在更新发生时随时了解更新状态的唯一方法。
Cookies和PHPSESSIONID
这是在PHP开发的应用程序中非常常见的。该API使用自己的自定义身份验证令牌,但是使用PHP默认会话处理功能的开发人员并不知道,所有响应也都包含可怕的PHPSESSIONID cookie!从长远来看,这会导致各种错误,因为没有人(包括开发人员)被告知有关cookie的信息,因为没有人认为他们将cookie放在了那里。
通常,REST并未明确禁止Cookie。如果使用不当,它们可能会引起麻烦(例如,如果您尝试访问也应通过API机制授权的域),应避免同时使用多种形式的身份验证。
关于PHP的会话处理,除非您使用PHPSESSIONID cookie充当API的身份验证令牌(我不建议这样做!),否则您永远不要依赖API的默认PHP cookie方法。我的建议是实施一个自定义会话处理机制,该机制可实现您的首选身份验证方法。
不要暴露内部错误或实施细节
多年来,即使在大公司流行的API中,我也无数次看到这种情况。在响应中暴露内部错误(例如SQL)不是很酷!寻找一种可靠的方式来记录这些日志以备将来参考,也可以将它们统一转换为API响应中的500 —内部服务器错误。
开发过程的早期应该做的第一件事,就是对于Web上公开的服务,安全性应该是首要考虑的问题~~~~