从HTTP流量中创建OpenAPI

303 阅读6分钟

在每年的这个时候,我们都在考虑我们要做的不同的事情,我们已经推迟了很久的新做法,以及我们想避免继续到下一年的错误。对于我们API领域的许多人来说,这将是转向API设计优先,使用像OpenAPI这样的标准,在编写任何代码之前很久就对API进行规划和原型设计。

更多的组织正在使用OpenAPI转向API设计优先,这要归功于工具供应商的巨大努力--从较大的家伙:StoplightPostman,到较小的开源OpenAPI工具--使得它更容易做到。

不幸的是,我们中的许多人陷入了一个尴尬的境地。我们有一个多年前建立的API,而现在我们的DevRel团队想要基于OpenAPI的API参考文档,API治理团队想要OpenAPI被包含在任何代码变更的拉动请求中,测试团队想要我们的OpenAPI来建立端到端的合同测试,但我们没有任何OpenAPI......AGH!

我们之前写过一些略显笨拙的方法来创建OpenAPI,比如Postman Collections,使用JSON到JSON Schema的转换器,以及一大堆乱七八糟的东西,但幸好现在有更好的解决方案。一个特别好的工具是Akita!

Akita是一个可观察性工具,它可以嗅探HTTP流量,并为你的数据建立模型。一旦完成了这些,它就可以创建一个你所有的API的图表,以便深入了解系统,智能地捕捉和沟通突发变化,以及其他各种方便的事情。

我们将使用它的部分功能,在一个已经部署到生产中的API上创建OpenAPI,这样我们就可以在今后的任何新功能中使用API设计优先。

寻找一个例子并不难。我自己在今年早些时候就犯了这个错误。 我们急于为保护地球提供API。没有必要设计API,因为它必须与一个现有的植树伙伴所定义的合同相匹配,所以我们只是复制了他们的一些JSON,并按照这个粗略的形状进行编码,希望得到最好的结果。当然,这种急于求成的做法马上就在我们面前炸开了锅。第一个消费者的整合是很多可怕的试验和错误,花了很多时间,而当第二个消费者时,他们没有任何文档。我知道我知道。机械师的车总是坏的......

所以让我们继续吧。我们可以把Akita客户端安装在任何地方,也许可以把它安装在分期/生产服务器上以检测流量,但安装在笔记本电脑上对这个工作流程来说更容易:运行代理,嗅探请求/响应https://api.protect.earth/ ,然后导入Akita。这在秋田的文档网站上有很好的记录,但让我们专注于这个工作流程的具体部分。

第1步:在本地设置Akita客户端

前往akitasoftware.com并点击加入测试版。也许它已经出来了,所以点击注册,只是以某种方式给自己一个账户。

现在我们可以安装akita-cli客户端。在macOS上,这将是一个brew安装,对于其他所有的东西都有文档

brew tap akitasoftware/akita && brew install akita-cli

安装完成后,使用akita login 命令来登录。你要去找你的API密钥,它在秋田仪表板的设置中:

akita login
API Key ID: apk_0000000000000000000000
API Key Secret: ******************************
Login successful!
API keys stored in ${HOME}/.akita/credentials.yaml

第二步:中间人代理

为了拦截前往加密网站的HTTP流量(https:// ),我们可以使用免费的工具mitmproxy,这是另一个brew安装:

brew install mitmproxy

然后,我们要从mitmproxy抓取har_dump.py脚本,这将把他们代理上截获的流量变成一个HAR(HTTP归档格式)文件

wget https://raw.githubusercontent.com/mitmproxy/mitmproxy/master/examples/contrib/har_dump.py

准备开始行动。

第三步:使用代理

在一个终端会话中,运行代理服务器,加载har_dump.py脚本,并设置dump.har ,这样HAR文件将被保存在本地:

mitmdump -s ./har_dump.py --set hardump=./dump.har

如果它是工作的,代理将运行在localhost:8080 ,所以你可以在任何http客户端中使用它作为代理。

也许你是那些能记住curl工作原理的人之一:

curl -D - -k --proxy localhost:8080 https://api.protect.earth/v1/orders/c36916f7-7591-47e5-b069-f983b9c0f320

这将向保护地球API的https://api.protect.earth/v1/orders/{uuid} 端点发出请求,通过mitmproxy传递请求和响应,并将输出写入dump.har

在curl中做这些事情有点乱,所以我抓起Insomnia,在API中点击了一下,尽可能多地点击资源和集合,所以OpenAPI是基于它所看到的所有数据的超集,而不是只有一个JSON表示。

第四步:将HAR转换为OpenAPI

有很多工具可以将HAR转换为OpenAPI,但其中有些是旧的,有些是坏的,而大多数是两者都有。

秋田在这方面做得非常好,它可以处理所有的可空、可选、多态和一般有趣的数据!它可以尝试将HAR转换成OpenAPI。它可以尝试注意到字符串的格式,所有这些都为你节省了手动填写这些内容的时间。

akita apispec 命令可以将dump.har 导入到你的服务中,并给它一个名字。服务是protect-earth ,而规范只是被称为mySpec,因为那是文档中所说的,似乎并不重要:

akita apispec --traces dump.har --out akita://protect-earth:spec:mySpec

秋田的服务页面现在应该知道你刚刚上传的服务。

点击它,会有一个它所知道的端点的列表,其中的参数是用来避免重复不同UUID的端点或其他参数的,就像其他工具经常做的。

这些端点在秋田有所有的元数据关联,这意味着它已经准备好通过网络界面导出为OpenAPI了。

OpenAPI文件将被创建为YAML,在写这篇文章的时候,正在生产OpenAPI v3.0。理想情况下,它很快就会被更新到OpenAPI v3.1,但差别不是很大,可以手动更改

一旦你得到了这个OpenAPI YAML文档,你就可以把它塞进你的Git repo中,与你的代码并存。这可能并不完美,但你可以将Git repo与基于Web的OpenAPI编辑器(如Stoplight Platform)或本地文件编辑器(如Stoplight Studio)挂钩,或者在你喜欢的文本编辑器中手动处理YAML。

无论你怎么做,你都可以根据你的喜好来整理OpenAPI文档,并在完成后发布这些文档。