随着 RESTful API 在 WEB 应用程序界的大行其道,如何规范、优雅、易懂地设计和描述一套 RESTful API 成为了一个广泛的问题。在探索的过程中,开源开发者们提供了许多可通用的解决方案,Swagger 的 OpenAPI 便是其中之一。本文将带你快速上手 OpenAPI,对于更细节、权威的说明,请访问其官方文档。
为什么要使用 OpenAPI?
OpenAPI 作为一种 REST API 描述的规范,它允许使用者完整地描述任意一种 REST API 实体,这包括:
- 端点(如/user)与方法(GET)
- 操作参数和输出
- 权限认证
- 联系方式、证书等
这些 API 的描述可以以 YAML 或 JSON 的格式写成,方便学习并且具有高度可读性。在完成 API 文档的编写后,我们通常可以选用 Swagger UI 或 Swagger Editor 生成交互式的 API 文档。其中,我们将在本文主要谈到后者。Swagger Editor是一个基于浏览器的免费工具,您只需要在左侧写入满足 OpenAPI 规范的文档,在右侧即可得到一个交互式的图形化 API 文档。成品效果图如下:
基本结构
满足 OpenAPI 规范的文档可以用 YAML 或者 JSON 格式写就,本文推荐您使用前者,因其拥有更广泛的教程和完善的社区,但后者也能得到完整的支持。OpenAPI 目前的最新版为 3.0,使用老旧的 2.0 或更早版本可能带来语法混乱、功能残缺等问题,我们推荐您使用最新版来避免遭遇这些困扰。一个符合 OpenAPI 3.0 规范的文档大约如下所示:
1 | openapi: 3.0.0 |
注意:所有关键字均为大小写敏感的
您可以注意到,上面的示例文档实际上包含有四个板块:openapi
,info
,servers
和 paths
,他们分别指明了 OpenAPI 版本信息(解释器将根据此选择合适版本的语法尝试进行解析),文档源信息(这包含标题、描述和 API 版本号),服务器(在其中可以填入一个或多个服务器地址,也就是之后端点相对路径的基路径(base path),并包含他们的描述)和端点(endpoint)路径(均为相对路径)。前面三者是简单明了的,而后者则是我们需要描述的主体,对于 REST API 的实际定义均在此标签下进行。
API 的描述
端点和方法(Endpoints & Methods)
paths
标签的直接子标签的标签名即为端点名。如下,我们就定义了/user
,/weapon
两个端点:
1 | ... |
而根据 REST 设计风格我们知道,对于一个完整的 API,我们除了需要给出端点路径外,还需要明确方法。在 OpenAPI 3.0 中,只需要在端点的直接子标签内写入方法即可:
1 | ... |
此时方法和端点共同构成了一个结构完整的 API,会以一个可伸缩的 Tab 的形式显示在 Swagger Editor 右侧的渲染边栏内,但你会惊奇地发现,里面还什么都没有。因为这并不是结束,我们还需要给定 API 的传入参数、返回内容和格式。如果你足够贴心,还能为开发人员们留下几段以供参考的的样例。
传入参数(Parameters)与请求体(Request Body)
我们假设您已经对 HTTP 协议有充分的认识。您应该知道,一般的 HTTP 方法使用参数传递输入信息(指 query 模式,以字符串形式),而 POST 方法允许通过请求体传递输入内容(以二进制形式)。在 OpenAPI 里,两者的语法也略有不同。对于传入参数,事实上有四种可选的模式:path
,query
,headers
和 cookies
,他们分别是通过 /endpoint/{parameter}
和 /endpoint?parameter=value
格式的 URL,HTTP 请求头和 cookies 字段来实现的信息传递。更常用的前两者的 OpenAPI 写法如下:
1 | paths: |
在这里我们定义了两个参数,分别是 path
模式的 userId
和 query
模式的 queryString
,在他们的子标签中,schema
用于描述变量的“模式”,在其中,变量的类型、格式以及其他约束将会被描述。另外,你可以通过 required: true
来将一个参数设置为必选参数。
requestBody
与之类似而又不同,我们直接看语法:
1 | ... |
在 requestBody
中,我们通过 content
描述其内容,并通过 application/json
一类的标签描述内容的 MIME 类型。由于内容本身就是一个变量,因而我们需要先对其的模式进行描述。在这里我们使用了 type: object
,这表示它是一个 JSON Object,从而允许我们使用 properties
标签对其内的键值对进行描述,这点就类似于 parameters
了。需要注意的是,这些键值对并不支持 required
标签。
返回内容(Responses)
描述完输入(参数),自然也就该说说输出(响应)了。对于每个 Method,我们都需要定义一些响应来指导用户的使用,依旧先来看看例子:
1 | paths: |
可以看到,在 responses
标签下,我们首先需要列出我们可能返回的 HTTP 状态码,然后在该子标签下通过类似 requestBody
下的格式进行描述(二者本质上都一样,是二进制的数据串)。
样例(Examples)
由于 Swagger Editor 设置上的限制,我们不能在 OpenAPI 约束的条件下完成多样例的撰写和展示,一个可选的替代方案是在 content
的同级标签下增加一个 examples
标签,并以如下格式撰写内容:
1 | examples: |
Swagger 会将其转换为 JSON Object 格式并展示在 Responses 栏中。
更进一步
以上内容仅仅只是 OpenAPI 语法的入门,还有很多实用的特性(如复用 schema 等)等待你的发现。如果您想要进一步了解,可以通过高质量的官方文档来进行学习。谢谢您的阅读。