原文地址:https://dev.to/ama/10-points-to-consider-when-using-open-api-specification-3-to-document-your-rest-api-4c70作者:Adrian Matei
之前使用的是 Swagger 2.0(也称为 OAS 2),这次决定升级到 OpenAPI 规范(OAS)3。在这篇文章中,我将列出主要的升级过程中的要点和使用 OAS 3 记录 API 的要点。其中一些要点可能仍适用于之前的 OAS 2(前称 Swagger)文档,但值得一提,因为我之前没有充分注意到它们。
本文中的代码示例摘自 bookmarks.dev-api 的 OAS 3 规范,它在 Github 上的 openapi.yaml 文件中可用。结果可在 bookmarks.dev/api/docs/ 查看。
以下是需要考虑的十个要点:
阅读规范文章
阅读 A Guide to What’s New in OpenAPI 3.0 文章,该文章分享了 OAS 最新版本的一些主要更新,并详细介绍了从 OAS 2.0 过渡到 OAS 3.0 时需要了解的内容。这篇文章基于这个 1 小时长的网络研讨会 OpenAPI 3.0, And What it Means for the Future of Swagger。
转换器 Web 服务
使用 OpenAPI/Swagger 2.0 到 OpenAPI 3.0 转换器 Web 服务,将你的 Swagger 规范转换为 OpenAPI 3.0。
它在线可用 https://converter.swagger.io/,也可以作为 docker 镜像使用:
docker pull swaggerapi/swagger-converter:v1.0.2docker run -it -p 8080:8080 --name swagger-converter swaggerapi/swagger-converter:v1.0.2
使用 Swagger-Editor 实时验证你的规范并预览
Swagger Editor 允许你在浏览器中编辑 YAML 格式的 Swagger API 规范,并实时预览文档。
你可以在线使用它,也可以作为 npm 发布版本或 docker 镜像 使用。更多细节请查看该项目的 自述文件。
使用 Swagger UI 展示你的文档
Swagger UI 是一组 HTML、Javascript 和 CSS 资源,可以从符合 Swagger 的 API 动态生成漂亮的文档。
我间接地使用 Swagger UI Express。这样你就可以像我一样,通过 API 的一个路由访问 Swagger UI 文档,例如 bookmarks.dev/api/docs/。
app.js
中的代码片段:
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const swaggerDocument = YAML.load('./docs/openapi/openapi.yaml');
app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
将开放规范文件(这里是openapi.yaml
)包含在 nodemon 监视中(例如nodemon --inspect ./bin/www --watch src --watch docs/openapi/openapi.yaml
)很有帮助,这样你就可以在不手动重启 ExpressJS 服务器的情况下重新加载 UI。
4.1 使用 swagger-jsdoc 进行代码优先的方法
这里还值得一提的另一点是,你可以使用 swagger-jsdoc,通过代码中的 JSDoc
注释集成 Swagger。swagger-jsdoc
项目假设你希望用一种方式记录现有的、活跃的、工作中的代码,以“赋予”它生命,生成一个规范,然后可以馈送到其他 Swagger 工具中,而不是反过来。
目前我在一个 openapi.yaml 文件中集中管理文档,但以后我可能会考虑使用它。
使用 tags 对操作进行分组
你可以为每个 API 操作分配一个标签列表。这样 Swagger UI 和 Swagger Editor 会按标签显示操作,非常方便。要控制 Swagger UI 中的排序,你需要在根级别将它们添加为全局标签。在那里你还可以为它们添加描述和指向外部文档的链接。
这里是我为 API 使用的标签:
tags:
- name: root
description: 用于标记根端点
- name: version
description: 访问项目的版本和 gitSha1
- name: public-bookmarks
description: 访问公共书签
- name: personal-bookmarks
description: 对个人书签执行的操作
- name: user-data
description: 对用户数据执行的操作
- name: helper
description: 帮助端点/操作
使用 servers 数组指定 API 的一个或多个基本 URL
在 OpenAPI 3.0 中,你使用 servers
数组指定 API 的一个或多个基本 URL。servers 替换了 OpenAPI 2.0 中使用的 host
、basePath
和 schemes
关键字。每个服务器都有一个 url
和一个可选的 Markdown 格式的 description
。
servers:
- url: http://localhost:3000/api description: 用于开发的本地服务器
- url: https://www.bookmarks.dev/api description: 主(生产)服务器
使用 components 定义和重用资源
通常,多个 API 操作有一些公共参数或返回相同的响应结构。为避免代码重复,你可以将公共定义放在全局的 components
部分,并使用 $ref
引用它们。
例如,对于在多个操作中出现的书签列表响应,我在全局的 responses
部分下定义了一个 BookmarkListResponse
:
components:
responses:
BookmarkListResponse:
description: 书签列表
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Bookmark"
并在不同的操作中引用它(例如 get-public-bookmarks
):
/public/bookmarks:
get:
summary: 使用查询参数返回公共书签列表。
tags:
- public-bookmarks
description: |
* 如果存在 `q` 参数,则按其中包含的查询文本进行过滤(优先于 `location`)
* 如果存在 `location` 参数,则返回包含该 URL 的一个**公共**书签列表
* 否则**默认**返回最近添加的100个公共书签
> 如果没有返回过滤器的公共书签,则列表为空
parameters:
- $ref: "#/components/parameters/searchTextQueryParam"
- $ref: "#/components/parameters/limitQueryParam"
- $ref: "#/components/parameters/locationQueryParam"
responses:
200:
description: OK
$ref: "#/components/responses/BookmarkListResponse"
请注意上面的locationQueryParam
。它是在components > parameters
部分中定义的location
查询参数,然后在 API 规范的多个位置引用(其中之一就是上面的示例):
componentes:
parameters:
locationQueryParam:
name: location
in: query
description: location of the bookmark, usually an URL
required: false
schema:
type: string
添加示例使其更清晰
你可以为参数、属性和对象添加示例,使 OpenAPI 对你的 Web 服务的规范更清晰。示例可以被处理 API 的工具和库读取。例如,一个 API 模拟工具可以使用示例值来生成模拟请求。你可以为对象、单个属性和操作参数指定示例。要指定示例,你可以使用 example
或 examples
键。
例如,用于过滤书签的搜索文本可以有复杂的值,没有比一些示例更好的方式来解释它了:
components:
parameters:
searchTextQueryParam:
name: q
in: query
description: |
搜索查询(词语由空格分隔)。有特殊的过滤器可用:
* `lang:iso_language_code` - 例如 `lang:en` 表示英语,`lang:es` 表示西班牙语,`lang:de` 表示德语书签
* `site:site_URL` - 例如只从 [www.codepedia.org](https://www.codepedia.org) 网站返回 `site:codepedia.org` 书签
* `userId:UUID-user` - 仅在查询由用户 `userId` 提交的**公共**书签时使用
* `private:only` - 仅在查询个人书签时有意义
schema:
type: string
examples: # 多个示例
german:
value: "lang:de"
summary: 仅查找德语书签
site:
value: "site:codepedia.org"
summary: 仅查找域名为 **codepedia.org** 的书签
complex:
value: "exception handling [java] site:codepedia.org"
summary: 仅查找包含术语“exception”和“handling”、标记为“java”且域名为 **codepedia.org** 的书签
complex-private-only:
value: "exception handling [java] site:wiki.my-corporation.com private:only"
summary: 与上面相同,但仅在私人书签内
使用枚举定义常量
Open API 目前还不支持 JSON Schema 的 const 关键字,但你可以使用 enum
来定义一个值。例如,我知道验证错误的 HTTP 状态码为 400(错误请求),所以我可以这样建模:
components:
schemas:
ValidationErrorModel:
allOf:
- $ref: "#/components/schemas/BasicErrorModel"
- type: object
required:
- validationErrors
- httpStatus
properties:
httpStatus:
type: integer
enum: [400]
validationErrors:
type: array
items:
type: string
当然,你也可以像预期的那样使用枚举来指定请求参数或模型属性的值。例如,请参阅过滤个人书签时 orderBy
的可能值:
paths:
/personal/users/{userId}/bookmarks:
get:
parameters:
- $ref: "#/components/parameters/userIdPathParam"
- $ref: "#/components/parameters/searchTextQueryParam"
- $ref: "#/components/parameters/limitQueryParam"
- $ref: "#/components/parameters/locationQueryParam"
- name: orderBy
in: query
description: |
It is considered in the abscence of `q` or `location` parameters
Possible values:
* MOST_LIKES - personal bookmarks most liked by the community
* LAST_CREATED - personal bookmarks last added
* MOST_USED - personal bookmarks the user (owner) clicked the most
schema:
type: string
enum: [MOST_LIKES, LAST_CREATED, MOST_USED]
标记可能以后需要引用的资源
在这个过程中,我标记了很多 Swagger/OpenAPI 资源和工具,并在 我在 bookmarks.dev 上的 [openapi] 公共资源中公开。
以上即是使用 OpenAPI 规范 3 时需要记住的十个要点。
使用 Apifox 管理 API 文档
Swagger 管理接口有时很不方便,缺乏团队间的分享协作,所以我更推荐使用 Apifox。
Apifox 是一个比 Postman 更强大的接口测试工具,Apifox = Postman + Swagger + Mock + JMeter,Apifox 支持调试 http(s)、WebSocket、Socket、gRPC、Dubbo 等协议的接口,并且集成了 IDEA 插件。在开发完接口后,可以通过 Apifox 的 IDEA 插件一键生成接口文档,多端同步,非常方便测试和维护。
将 Swagger 导出为 JSON
如下图所示,选择“Convert and save as JSON”,将 Swagger 文档导出为 JSON 文件。
将 Swagger 文件导入 Apifox
打开 Apifox,创建一个项目后,选择“项目设置->导入数据->OpenAPI/Swagger->文件导入”,将已导出的 Swagger 格式的 JSON 文件导入即可。
导入时,会有预览,可以选择导入全部,也可以选择性的导入接口。
导入成功之后,就可以选择一个环境来测试接口。如下图所示,接口成功返回数据:
知识扩展: