专栏名称: 程序人生
十年漫漫程序人生,打过各种杂,也做过让我骄傲的软件;管理过数十人的团队,还带领一班兄弟姐妹创过业,目前在硅谷一家创业公司担任 VP。关注程序人生,了解程序猿,学做程序猿,做好程序猿,让我们的程序人生精彩满满。
目录
相关文章推荐
51好读  ›  专栏  ›  程序人生

构建下一代 HTTP API - OpenAPI spec 和解析器

程序人生  · 公众号  · 程序员  · 2020-12-14 21:05

正文

请到「今天看啥」查看全文


当我们定义了这样一种语言去描述我们如何从 feed 里获取想要得到的数据时,剩下的问题就是:

  1. 写一个 parser,能够处理这个语言

  1. 使用我们定义的语言为每个 feed 撰写这样一个配置

最后,我们把问题精简成 1 个 parser + X 个配置文件,代码量也就是几百行。而配置文件,培训一下几乎是个程序员就能写出来。其结构如下:

日后的维护就是如何去扩充 parser 的一些辅助性函数,以及为新的 feed 撰写配置。

如果你看懂了这个例子,就会发现: 很多问题都可以化简为定义一个承上启下的中间语言(DSL),然后为其构建一个 parser。

而 OpenAPI,恰恰是这样一个在 API 客户端和 API 服务器之间的中间语言。我们利用好它的程序属性,可以做很多自动化(客户端代码生成,服务端代码生成,服务端测试生成,etc.)。

OpenAPI spec 简介

Open API spec 3.1.0 全文一万四千字,A4 纸打印的话要八十多页,是个庞大但并不复杂的 spec。要能够通过它来生成代码,第一步我们需要将其正确解析,处理好各种各样的情况,也就是说,我们要为其写一个 parser。而要撰写这样一个 parser,我们首先需要读懂 OpenAPI spec。好在 OpenAPI spec 并不复杂,很容易读。

首先,OpenAPI 所有数据结构的验证都使用 JSON schema(略有扩展),所以这部分我们只要大致了解一下,等具体使用的时候再详细看。JSON schema 有很久的历史了,所以相关的包也很多,各种语言的社区都找得到。在 Quenya 里,我就「暂时」使用了 ExJsonSchema 这个库。

然后,我们关注几大核心对象即可。

Server Object

Server object 在 swagger UI 里很有用,它定义了 API 可以通过什么 API 访问,以及 base path 是什么。比如: http://localhost:4000/api/v1 ,这里声明了 API 运行在 localhost ,使用 http 访问,端口是 4000 ,base path 是 /api/v1 。这些信息都会被用在 Quenya 生成 API 代码时。比如:

servers:  - url: http://localhost:4000/api/v1    description: Local dev server  - url: https://api.todo.mvc/v1    description: Production server

OpenAPI Spec 不对 Server Object 做任何限制,但在 Quenya 里,至少要声明一个 localhost ,Quenya 会用这里的信息来正确生成本地运行的服务器监听的端口以及正确的路由,比如:

get("/swagger/main.json", to: SwaggerPlug, init_opts: [app: :todo])get("/swagger", to: SwaggerPlug, init_opts: [spec: "/swagger/main.json"])forward "/api/v1", to: Todo.Gen.ApiRouter, init_opts: []
match(_, to: Quenya.Plug.MathAllPlug, init_opts: [])

这个很重要,我们要确保生成的 API 服务可以无需任何修改就能在 swagger 里运行。

Path / Operation object

在任何 API 项目中,最核心的部分就是每条路由及其处理函数的定义。在 OpenAPI spec 中,这是由 Path 以及 Path 内部的 operation 对象定义的。比如如下的 path todo/{todoId} 包含一个 patch operation,它的定义如下:

/todo/{todoId}






请到「今天看啥」查看全文