使用 OpenAPI 3.0 规范记录 RESTAPI 时需要考虑的这 10 点

本文将列出主要的升级过程中的要点和使用 OAS 3 记录 API 的要点。其中一些要点可能仍适用于之前的 OAS 2(前称 Swagger)文档,但值得一提,因为我之前没有充分注意到它们。

用 Apifox,节省研发团队的每一分钟

使用 OpenAPI 3.0 规范记录 RESTAPI 时需要考虑的这 10 点

免费使用 Apifox

相关推荐

最新文章

API

一体化协作平台

API 设计

API 文档

API 调试

自动化测试

API Mock

API Hub

立即体验 Apifox
目录
原文地址: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 注释集成 Swaggerswagger-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 中使用的 hostbasePathschemes 关键字。每个服务器都有一个 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 模拟工具可以使用示例值来生成模拟请求。你可以为对象、单个属性和操作参数指定示例。要指定示例,你可以使用 exampleexamples 键。


例如,用于过滤书签的搜索文本可以有复杂的值,没有比一些示例更好的方式来解释它了:

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 导出为 JSON
将 Swagger 导出为 JSON

将 Swagger 文件导入 Apifox

打开 Apifox,创建一个项目后,选择“项目设置->导入数据->OpenAPI/Swagger->文件导入”,将已导出的 Swagger 格式的 JSON 文件导入即可。

将 Swagger 文件导入 Apifox
将 Swagger 文件导入 Apifox

导入时,会有预览,可以选择导入全部,也可以选择性的导入接口。

Apifox 选择性的导入接口
选择性的导入接口

导入成功之后,就可以选择一个环境来测试接口。如下图所示,接口成功返回数据:

Apifox 接口导入成功
接口导入成功


知识扩展: