swagger在线api文档搭建指南,用于线上合适么?

Java 投稿 66500 0 评论

swagger在线api文档搭建指南,用于线上合适么?

其实写 api 文档这个事情也没有一个统一的标准,写这篇文章更多地是分享与记录自己的一些心得体会。

所以,或许写 api 就像比武功吧,一招一式耍出来后,花架子或许能唬住大众,高手之间的交流则只可意会不可言传.....。

但关于怎么写 api 文档这样的业务小常识,感觉还是可以分享一下的!

让人又爱又恨的 api 文档

毕竟工作本来就累,这代码一写完,测试不找碴已经是万幸了,要顺便改上几个 bug,谁还记得维护 api 文档嘛。

所以,为了方便自己,同时也能方便他人,我们还是要把编写 api 文档这件事情放在心上。

api 文档一般是由服务端同学定义的,但最好能由前后端同学一起定初稿;一个人设计容易有疏漏与盲区,两个人一起设计往往双方都能得到进步。我自己在定义 api 的时候也常常会和前端同学交流一下想法,前端同学往往能给出一些建议,大家磨合后开发就会比较顺畅。(一开始可能会在开发的过程中改动初始设计,慢慢设计多了,返工的概率就减少了)

api 文档需要说明的内容

我在想有没有一种可能,等我的系列文章更新完后,云你好服务就正式上线商用了...... 别小瞧它只是云你好哦,阿菌会在这系列文章里分享所有自己在当前工作中的心得体会与思考,由浅入深,希望能给大家带来一点点启发,也欢迎各路大佬前来指点交流。

# 云你好服务 API 接口回顾:
@app.get("/api/v1/hello")
def hello():
    # 看用户是否传递了参数,参数为打招呼的目标
    name = request.args.get("name", "")
    # 如果传了参数就向目标对象打招呼,输出 Hello XXX,否则输出 Hello World
    return f"Hello {name}" if name else "Hello World"

首先我们要给出描述信息:

描述信息:云你好 api,大家可以通过云你好,获得一次来自云端的问候

然后要给出 api 的请求方式:

请求方式:GET

接着要给出请求地址:

http://127.0.0.1:5000/api/v1/hello

然后要给出请求参数:

状态码:200
"hello 阿菌"

状态码:400
"您的余额不足了,不能打招呼了"

状态码:500
"sorry~服务器开小差了"

简单来说就是要把调用 api 各种可能出现的情况告诉用户,我们顺便完善一下云你好的代码,让云你好服务可以容纳以上述三种情况:

# 云你好服务 API 接口
@app.get("/api/v1/hello")
def hello():
    """
    首先判断用户的余额够不够
    假设我们已经写好了判断逻辑,
    后面我们讲 cookie,session,header 等知识的时候会补充
    """
    try:
        if not enough_money():
            return "您的余额不足了,不能打招呼了", 400

        # 看用户是否传递了参数,参数为打招呼的目标
        name = request.args.get("name", "")

        # 如果传了参数就向目标对象打招呼,输出 Hello XXX,否则输出 Hello World
        return f"Hello {name}" if name else "Hello World", 200

    except Exception:
        # 假设在使用云你好服务的过程中出现了异常
        return "sorry~服务器开小差了", 500

请求响应设计小加餐

当然,云你好只是个极简的例子,企业开发中是不会直接返回字符串的,一般会约定一个数据格式,比如状态码为 200 返回:

{
    "items": ["xxx", "yyy", "zzz", ...],
    "total": 10
}

状态码非 200 的响应,也就是请求发生错误的响应数据格式会是这样的:

{
    "msg": "sorry~ something went wrong..."
    "msg_cn": "sorry~服务器开小差了..."
    "error_code": "20000"
    "detail": {
        "xxx": "...."
    }
}

刚开始学编程的时候我不太明白,既然已经有了响应码,比如 400,500,为什么还要弄一个 error_code 呢?

有了错误码,我们则可以根据每一种情况定义一个错误码,比如:

以下均为 404 错误
* 用户名不存在 - error_code: 10000
* 收货地址不存在 - error_code: 10001
* 手机号不存在 - error_code: 10002
* 邮箱不存在 - error_code: 10003

这样在开发联调定位错误的时候是非常方便的,而且我们还可以根据不同的状态码,设置不同的报错信息。

如何让 api 文档看起来更舒服

上面我们介绍了为一个 api 编写文档需要对外提供哪些信息,虽然我们知道了要写什么,但是离写出一个好看的 api 文档还是有一定距离的。

  1. 我们每次写 api 文档时的心情不一样,有的时候我们心情特别好,写 api 文档就会特别认真,会详细且准确地描述每一个参数;但我们总会有心情不好的时候,为了在心情不好的时候也能对自己的行为做出约束,我们得想一些办法。

  2. api 文档的样式。如果仅仅用一个在线文档(甚至用word/pdf)写 api,我们自己定义的格式通常是比较普通的,为了让 api 文档的阅读者(比如我们自己)有一个好心情,我们得想办法弄个好看点的样式。

  3. api 文档给出的示例要是能够运行调试就更好了。

这个时候我们可以使用一些外部的 api 文档软件,帮助我们构建出一份漂亮的 api 文档。而 api 文档工具软件,业内首推的就是 swagger 了,免费又好用。

善用 Github 上的开源工具

由于云你好是用 python 的 flask 框架搭建的(选择 python 讲解是因为 python 代码就像说大白话,配合注释容易让大家看懂),当我们想要使用某项主流技术的时候,首先可以去 Github 上搜一下有没一些好用的脚手架,这样可以避免重复造轮子。

接着我们看第二个快 3k 星星的 flasgger 框架,点进去后直接看示例,看看如何能把软件跑起来。

from flask import Flask, request
from flasgger import Swagger, swag_from

app = Flask(__name__)
swagger = Swagger(app)


# 云你好服务 API 接口
@app.get("/api/v1/hello")
@swag_from('hello.yml')
def hello():
    try:
        if not enough_money():
            return "您的余额不足了,不能打招呼了", 400

        # 看用户是否传递了参数,参数为打招呼的目标
        name = request.args.get("name", "")

        # 如果传了参数就向目标对象打招呼,输出 Hello XXX,否则输出 Hello World
        return f"Hello {name}" if name else "Hello World", 200

    except Exception:
        # 假设在使用云你好服务的过程中出现了异常
        return "sorry~服务器开小差了", 500


if __name__ == '__main__':
    app.run()

swagger 可以通过 yml 格式描述一个 api 的详细信息,可以描述的 api 信息包括且不限于我们上文提到的 api 文档需要说明的内容:

云你好 api
---
parameters:
  - name: name
    in: query
    type: string
responses:
  200:
    description: "请求成功"
    schema:
      examples: "Hello 阿菌"
      type: string
  400:
    description: "客户端错误"
    schema:
      examples: "您的余额不足了,不能打招呼了"
      type: string
  500:
    description: "服务端错误"
    schema:
      examples: "sorry~服务器开小差了"
      type: string

然后我们可以把云你好服务运行起来,访问  后能得到一个这样的界面:

api 文档部署小加餐

api 文档其实是语言无关的,不管我们用的是 java、python、golang 什么语言都好,想要得到这样的一份 api 文档,关键在于编写好 yml 文件,描述好我们每一个 api 的用途,请求参数以及响应。

事实上,企业级应用是很少会这样部署 api 文档的,我先带大家看一下 flasgger 大概是怎么把 swagger 集成到我们的后端服务器的,我们可以从运行情况进行反推。

/Users/game-netease/Desktop/flaskProject/venv/bin/python -m flask run
 * Serving Flask app 'app.py' (lazy loading)
 * Environment: development
 * Debug mode: off
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
127.0.0.1 - - [13/May/2022 08:48:33] "GET /apidocs/ HTTP/1.1" 200 -
127.0.0.1 - - [13/May/2022 08:48:33] "GET /flasgger_static/lib/jquery.min.js HTTP/1.1" 304 -
127.0.0.1 - - [13/May/2022 08:48:33] "GET /flasgger_static/swagger-ui-bundle.js HTTP/1.1" 304 -
127.0.0.1 - - [13/May/2022 08:48:33] "GET /flasgger_static/swagger-ui.css HTTP/1.1" 304 -
127.0.0.1 - - [13/May/2022 08:48:33] "GET /flasgger_static/swagger-ui-standalone-preset.js HTTP/1.1" 304 -
127.0.0.1 - - [13/May/2022 08:48:34] "GET /apispec_1.json HTTP/1.1" 200 -

从 flask 为我们打印的请求路径可以看出,flasgger 其实是把一系列 swagger 的静态资源集成到了我们的后端服务中,并且把对应的路由注册到了后端框架的路由表里,当我们访问  这样的路径时,它返回了相应的静态资源给浏览器渲染。

所以,对于云你好服务来说,假设我们架设了静态资源服务器,更合理的 api 文档部署方案或许该是这样的:

好了,"云你好"服务第二集暂时就更新到这里了,这个系列的文章会比较长,希望在一步步搭建云你好服务的过程中,继续和大家分享我在写代码过程中的一些思考,下一期更精彩!

编程笔记 » swagger在线api文档搭建指南,用于线上合适么?

赞同 (79) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽