设计,测试和发布API时要考虑的43件事情-Web API检查清单

在设计,测试或发布新的Web API时,您需要在现有复杂且复杂的系统之上构建新系统。至少,您正在构建基于TCP / IP的HTTP,它基于一系列管道。您还在构建Web服务器,应用程序框架和API框架。

大多数人,包括我自己,都不知道他们正在构建的每个组件的所有复杂性和细微差别。即使你深刻理解每一个组成部分,也可能会得到太多的信息,无法一次性把握住你的脑海。

“我们知道有知道的知识:有些我们知道的知识。我们也知道有未知的知识:也就是说我们知道有些我们知道的事情我们不知道。但也有未知的未知数 - 我们不知道的我们并不知道。“ - 防务部长唐纳德拉姆斯菲尔德,国防部介绍

我不想让你建立一个API,并且只有在他们咬你时才知道你未知的未知数。因此,这里列出了一系列明显而细微的事情,在设计,测试,实施和发布Web API时很容易被忽略。

HTTP

HTTP 1.1规范,RFC2616,在54121个字大幅文档。以下是可能影响您的API设计的规格中的一些选择项目:

#1。幂等方法 - GET,HEAD,PUT,DELETE,OPTIONS和TRACE都旨在成为幂等操作; 即“N> 0个相同请求的副作用与单个请求相同”(RFC2616§9.1.2)

#2。身份验证 - 大多数API都需要一种方法来识别和验证访问API的用户。HTTP 为此提供了授权标头(RFC2616§14.8)。RFC2617规定了特定的认证方案,包括最常见的HTTP基本认证。许多流行的API使用HTTP基本身份验证和API密钥作为用户名或密码。这是一个简单有效的认证机制。要准确实现HTTP身份验证,如果由于缺少身份验证而导致请求不被允许,您应该提供带有WWW-Authenticate头的401状态码。在发送后续请求的授权标头之前,许多客户端都需要此响应。

#3。201创建 - 使用“201 Created”响应代码表明请求已成功处理并导致创建新资源。201响应可以包括位置标题中的新资源URI。(RFC2616§10.2.2)

#4。202已接受 - 使用“202已接受”响应码来表明请求有效并将被处理,但尚未完成。通常这用于服务器端背景中可能存在处理队列的情况。(RFC2616§10.2.3)

#5。4xx与5xx状态码 - 4xx和5xx状态码之间有一个重要的区别:4xx码用于指示客户端错误,而5xx码用于指示服务器端错误。正确使用这些状态代码类可以帮助应用程序开发人员了解他们是否做了错误的事(4xx)或某些事情是坏的(5xx)。(RFC2616§6.1.1)(编辑:阅读更多关于Is 404“Not Found”的差异是否真的是客户端错误?)

#6。410 Gone - “410 Gone”响应代码是未充分利用的响应代码,它通知客户端此URL中存在资源,但不再是此资源。这可以在您的API中使用,以指示删除,存档或过期的项目。(RFC2616§10.4.11)

#7。期望值:100-继续 - 如果API客户端即将发送带有大型实体主体的请求,例如POST,PUT或PATCH,则可以在其HTTP头中发送“Expect:100-continue”,然后等待“100 Continue”响应,然后发送其实体。这允许API服务器在浪费带宽返回错误响应(例如401或403)之前验证请求的大部分有效性。支持此功能并不常见,但它可以提高API响应能力并在某些情况下降低带宽。(RFC2616§8.2.3)

#8。连接保持活动 - 保持与API服务器的连接以获得多个API请求可以大大提高性能。如果配置正确,几乎每个Web服务器都应该支持保持连接。

#9。HTTP压缩 - HTTP压缩既可以用于响应主体(Accept-Encoding:gzip),也可以用于请求主体(Content-Encoding:gzip)以提高HTTP API的网络性能。

#10。HTTP缓存 - 在您的API响应中提供缓存控制标头。如果它们不可缓存,“Cache-Control:no-cache”将确保代理和浏览器能够理解这一点。如果它们是可缓存的,则需要考虑各种因素,例如缓存是否可以由代理共享,或者资源“新鲜”多久。(RFC2616§14.9)

#11。缓存验证 - 如果您有可缓存的API匹配,则应在响应中提供Last-Modified或ETag标头,然后为条件请求支持If-Modified-Since或If-None-Match请求标头。这将允许客户端检查他们的缓存副本是否仍然有效,并在不需要时阻止完整的资源下载。如果实施得当,您可以使您的条件请求比平常请求更高效,并且还可以节省一些服务器端负载。(RFC2616§13.3)

#12。有条件的修改 - ETag头文件也可用于对资源进行条件修改。通过在你的GETs上提供一个ETag头,稍后POST,PATCH或DELETE请求可以提供一个If-Match头来检查他们是否正在更新或删除它们上次看到的相同状态的资源。(RFC2616§14.24)

#13。绝对重定向 - HTTP / 1.1的一个鲜为人知的要求是重定向(例如,201,301,302,303,307响应代码)应该在位置响应头中包含绝对URI。许多客户端在Location中支持相对URI,但是如果您希望您的API与许多客户端广泛兼容,则应该在任何重定向中使用绝对URI。(RFC2616§14.30)

#14。链接响应头 - 在RESTful API中,即使响应的内容类型没有自然的方式提供链接(例如,PDF或图像表示),通常也需要提供指向其他资源的链接。RFC5988指定了在响应头中提供链接的方法。

#15。规范URL - 对于具有多个URL的资源,RFC6596定义了提供规范URL链接的一致方法。

#16。分块传输编码 - 如果您的内容响应较大,则传输编码:分块是将响应传输到客户端的好方法。它将减少服务器和中间服务器的内存使用需求(特别是对于实现HTTP压缩),并提供更快的首字节响应时间。

#17。分块传输编码中的错误处理 - 在您开始实施分块传输编码之前,请确定如何处理中间请求发生的错误。一旦开始流式传输您的响应,您将无法更改您的HTTP状态代码。通常,您会定义一种在内容类型中表示错误的方法。

#18。X-HTTP-Method-Override - 一些HTTP客户端不能支持除GET和POST之外的任何内容; 您可以通过POST对其他HTTP方法进行隧道传输,并使用事实上的标准X-HTTP-Method-Override头来记录“真实”的HTTP方法。

#19。网址长度 - 如果您的API支持复杂或任意过滤选项作为GET参数,请记住,客户端和服务器可能存在长度超过2000个字符的URL的兼容性问题。

API设计

#20。无状态 - 有一个地方你不希望你的API存储状态,这是你的应用程序服务器。始终保持应用程序服务器无状态,以便可以轻松轻松地进行缩放。

#21。内容协商 - 如果您想要支持多种资源表示形式,您可以使用内容协商(例如接受标题)或针对不同表示形式(例如。??format = json)的不同URL,也可以将两者结合起来内容协商资源重定向到特定格式。

#22。URI模板 - URI模板是一种定义良好的机制,可为您的客户提供URL组合功能,或将您的URL访问模式记录到最终用户。

#23。Design for Intent - 不要仅仅通过你的API暴露你的内部业务对象。将您的API设计为具有语义含义并匹配您的用户将拥有的用例。Darrel Miller 在API Craft上写了一篇很棒的文章,描述的比我所能做到的要好。(编辑:我在一篇名为“ 停止设计易碎Web API”的文章中尽力而为。)

#24。版本控制 - 理论上讲,如果您事先设计了一个非常棒的API,则可能永远不需要在API中创建不兼容的内容。对于我们的实用主义者,请将版本信息放入API URL(例如,a / v1 /路径)中,以便在API无法正常工作的情况下拥有安全网。(编辑:扩展的理由是我的后续文章:是不是没有人有时间:API版本)

#25。授权 - 请记住,在设计您的API时,并非所有用户都有权访问系统中的所有对象。如果您使用或构建具有某种形式声明性安全性的API框架,以便在读取和写入资源访问权限时轻松分配和修改授权权限,那就太好了。

#26。批量操作 - 大多数客户端如果能够发出更少的请求来获取或修改更多数据,则性能会更好。在您的API中构建批量操作以支持这种用例是个好主意。

#27。分页 - 分页在API中有两大目的; 它减少了传递给客户端的不必要数据量,并减少了应用程序服务器上不必要的计算量。用于制作分页收集资源的模式有很多种,如果你不知道从哪里开始,请通过Stackoverflow浏览一些提示。如果您想成为我的个人英雄,请通过提供指向时间戳或版本控制的其他页面的链接来实现一致的分页,这样,即使所涉及的对象发生更改,也不会在分页请求中看到重复的结果。

#28。Unicode - 现在很明显,您需要在Web服务中支持超过英文字符; 请记住在设计和测试API时要牢记这一点。尤其是,如果您在URL中使用Unicode字符作为自然键(例如,/ users / jimbob / become / users /싸이/),则Unicode字符会很有趣。

#29。错误日志记录 - 确保你设计你的API如何执行错误日志记录,而不是将它们放在一起。特别是,我发现区分由客户端输入引起的错误和由您的软件引起的错误非常有价值。将这些保存在两个独立的日志中

内容

#30。内容类型 - 整本书可以写成关于内容类型; 我要指出的是,它们很重要。就个人而言,我喜欢重复使用其他人开发的内容类型,如Atom,Collection + JSON,JSON HAL或XHTML。定义您自己的内容类型比您期望的要多。

#31。HATEOAS - 作为应用程序状态引擎的超媒体是一种REST约束,简而言之,它意味着你的内容应该通过链接和表单告诉客户它能做什么。如果你用这个约束来构建你的API,它会变得更加灵活,如果你的客户也遵循你的设计方法。

#32。日期/时间 - 当您在API中提供日期/时间值时,请使用包含时区信息的格式。RFC3339是ISO 8601的一个子集,是最简单的日期和时间格式。

安全

#33。SSL - 考虑您是否应该在HTTP和HTTPS下提供您的API,或者仅使用HTTPS。独占HTTPS是一种越来越流行的选择。

#34。跨站点请求伪造(CSRF) - 如果您的API接受与您的交互式用户使用相同的身份验证配置,那么您可能容易受到CSRF攻击。例如,如果您的交互式用户登录并获取“SESSIONID”cookie,并且该cookie也可用于调用API请求,那么仔细编写的HTML表单可能会代表您的用户发出意外的API请求。(编辑:了解更多关于保护API免受CSRF攻击的信息)

#35。节流 - 确保一个API用户不能通过编写一个非常愚蠢的API客户端来降低系统性能。它偶然和恶意地发生。如果一个API用户超出了您应该为其提供的大量API请求限制,请使用Retry-After标题给它们一个503响应。

#36。微妙的拒绝服务 - 限制应该可以防止某人以最简单的方式砸碎你的API,但是也有很多微妙的拒绝服务攻击。Slowloris,Billion笑和ReDoS都是DoS攻击的有趣例子,不需要大量源资源,但它们可以让API快速耗尽资源。

客户

无论您是向用户提供测试代码,还是为他们构建SDK,请检查您是否向他们提供遵从以下几条简单规则的客户端:

#37。连接保持活动 - 某些HTTP客户端库要求您执行一些额外工作以启用持久连接。持续连接可能会对您的API的感知性能产生重大影响。

#38。授权之前的401 - HTTP客户端的另一个怪癖是,他们通常需要一个“401 Unauthorized”响应,然后才会发出带有授权标头的请求。这会给API请求增加很多时间,尤其是在高延迟困难的移动网络上。

#39。期望值:100-继续 - 我知道至少有一个API客户端默认使用“Expect:100-continue”; 如果它没有收到“100继续”响应,它会在3秒超时后继续请求。如果您不支持“100继续”,这将成为另一个可以禁用客户端的性能拖放。

其他的东西

#40。文档 - 编写API文档可能是一个真正的难题,但手写文档通常是最好的文档。确保包含一些可运行代码或卷曲命令行,以尽快帮助人们实现速度。您还可以查看文档工具,如apiary.io,Mashery I / O文档或Swagger。

#41。与客户一起设计! - 不要在真空中设计您的API; 与客户和他们的使用案例一起工作。这将帮助你“设计意图”(#23)。

#42。反馈 - 确保您向API用户提供一种方法,向您提供有关API的反馈。这可以通过您的支持渠道,或者它可以是一个托管论坛,或者一个邮件列表。尽可能让您的用户尽可能无摩擦。

#43。自动化测试 - 您的API应该是您构建自动化测试所用的最简单的东西。毕竟,它是为自动化而制造的。利用它!

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180311A0SSWH00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券