『Swagger 上手』

大纲

  • 问题
  • RestfulAPI

API

  • 动作
  • 请求:Url、Body
  • 返回信息:Status_code、Response

在开发过程中,经常会遇到和其他组件或者服务进行交互的情况,和服务器交互,好理解,平时的上网就是在和服务器交互:向服务器发送请求,服务器接收到请求之后,根据请求的动作,进行相应的动作响应。

可以看出这种方法方式是通过:发送请求,返回响应的这一套动作进行的,即客户端、服务器模式,发送请求的一端一般认为是客户端,返回响应的一端认为是服务器端。

软件设计领域,将这一套机制统一起来,方便进行通信:即 Restful api。

简单的来说:比如需要开发一个软件,软件的细节不让使用者看到,但是使用者又有可能需要访问到软件服务上的某些资源。这个时候就应该定义一套API, 让使用者调用这套API就能获取或者更新或者删除服务上的资源。

最近的接触的业务开发相互之间的访问都是通过API 访问,相互之间无需知道内部细节。

在这个过程中,约定的API 经常随着开发的进行而需要进行改动,有对请求进行更改的,有对返回信息进行修改的,也有对状态码定义的修改的。变动的API 对开发的要求很高,导致进行重复或者无效的开发。

伟大的开源领域一定有相应的解决方法。

Swagger 就是这么一套简单但功能强大的API 表达工具。本教程就是让读者学会使用这个工具的使用。

1. 思考

让你设计这套API 可视化工具,你会怎么设计?

和API 相关的又有哪些东西需要呈现?

举个例子:未经可视化的API 的一般定义会是这样


GET: /api/v1/designer/paas/{paasid}

Request: null

Response:
  - 200
  - {
      paasidinfo: ""
  }
  
  - 404
  - {
      status: no exist the paasid
  }



curl http://127.0.0.1:5000/api/v1/designer/paas/admin_123

200
{
    paasinfo: "create new paasid : admin_123"
}

从上面的示例和API 相关的东西包括;

  • http: 动作:Get、Post、Put、Delete
  • URL:访问路径:带参数和不带参数
  • 返回信息:状态码和返回信息

主要是这三类。这三类定下来,API 基本就定下来。

2. Swagger 是怎么做的

平时定义这么一套API 的方法大概和举例差不多,那Swagger 是如何做的呢?

Swagger 是通过定义一个配置文件的形式,这套配置文件有它约定的语法,再通过对配置文件的处理,可视化出API。除此之外,通过Swagger 生成的API, 可以得到交互式的文档,自动生成代码的SDK以及API 的发现特性等。

本文暂探讨配置文件的编写,生成可视化的API。

3. 配置文件的形式

一般的配置文件的形式有这么三种:

  • json
  • yaml
  • ini

这三种很常见,其中json 的方式很普遍,但是可读性不好,尤其是嵌套处理的字段更不好阅读。


{
    "swagger": "2.0",
    "info": {
        "version": "1.0.0",
        "title": "Simple API",
        "description": "A simple API to learn how to write OpenAPI Specification"
    },
    "schemes": [
        "https"
    ],
    "host": "simple.api",
    "basePath": "/openapi101",
    "paths": {
        "/persons": {
            "get": {
                "summary": "Gets some persons",
                "description": "Returns a list containing all persons.",
                "responses": {
                    "200": {
                        "description": "A list of Person",
                        "schema": {
                            "type": "array",
                            "items": {
                                "properties": {
                                    "firstName": {
                                        "type": "string"
                                    },
                                    "lastName": {
                                        "type": "string"
                                    },
                                    "username": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

上文这个json 体很容易出错,如果没有静态格式检查工具,很容易漏掉{}

ini 这种形式很简单,但也适用于简单场合,不易处理复杂的嵌套场景


[hostname]
127.0.0.1

[name]
xiewei

[server]
10.100.100.100, 10.100.100.101



yaml 这种形式阅读性最好,其次可以对文本内容进行注释,整体的效果最佳,很适用于配置文件。

swagger: "2.0"

info:
  version: 1.0.0
  title: Simple API
  description: A simple API to learn how to write OpenAPI Specification

schemes:
  - https
host: simple.api
basePath: /openapi101

paths:
  /persons:
    get:
      summary: Gets some persons
      description: Returns a list containing all persons.
      responses:
        200:
          description: A list of Person
          schema:
            type: array
            items:
              required:
                - username
              properties:
                firstName:
                  type: string
                lastName:
                  type: string
                username:
                  type: string

可以看出整体的这种键值对的形式阅读的效果很好。

任何编程语言,对json, yaml,ini 格式的配置文件的处理和很方便,接口都很简便,比如 Python,Go

4. 配置文件的内容

简单分析完配置文件的格式的优缺点,再来分析下配置文件的内容。

这里到不是具体的分析文件内容的值,而是分析配置文件的内容的数据类型。

总结下来有下面三种:

  • 键值对:key: value
  • 数组
  • 纯量:整型、字符串、布尔型

不管是Json 或者 Yaml 文件的组成都是这三种形式的混合

  • 键值对
{
    name: xiewei
}
name: xiewei
  • 数组
name :["xiewei1", "xiewei2", "xiewei3"]



name:
  - xiewei1
  - xiewei2
  - xiewei3
  
  • 纯量
"xiewei"
false
123
xiewei
123 
true

5. Swagger 的使用

离线形式

  • 下载地址: Swagger
  • 浏览器打开 index.html 文件

在线形式

打开后都存在一个默认的配置文件,左边是配置文件,右边是可视化结果。

微信截图_20180130214149.png

配置文件看上去很复杂,其实都是在实现这么一句话:

API的基本组成部分,包括提供给API消费者的不同HTTP请求方法、路径,请求和消息体中的参数,以及返回给消费者的不同HTTP状态及响应消息体。

即:

  • http 动作
  • url
  • 请求体
  • 返回信息

Swagger 定义了一些特殊的字段来实现这个目标,我们只需要熟悉一些特殊的字段,就能实现API 的定义。

整个Swagger 配置文件的格式为 yaml。梳理了下,配置文件主要包括下面三个部分:

  • API 的描述信息
  • API 的URL 信息
  • API 的操作
    • http 动作
    • url
    • 请求
    • 响应

一个简易的配置文件形式大概是这样的:


swagger: "2.0"
info:
  description: "This is a sample server Petstore server.  You can find out more about     Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).      For this sample, you can use the api key `special-key` to test the authorization     filters."
  version: "1.0.0"
  title: "Swagger Petstore"
  termsOfService: "http://swagger.io/terms/"
  contact:
    email: "apiteam@swagger.io"
  license:
    name: "Apache 2.0"
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "petstore.swagger.io"
basePath: "/v2"

schemes:
- "http"
paths: {}

上面的信息不是所有的都是必须的。

  • info、title、description 、version 等表示的是API 版本信息
  • host、basePath、schemes 等表示的是API 的URl 信息
  • paths 下面的值表示的是API 的操作

效果大概是这样的:


微信截图_20180130214245.png

下面举例:

原始API 为:

POST  /api/v1.0/designer/paas/{paasid}
Request
{
  "git": {
    "addr":"ssh://ipaddr/path/.git",
    "branch":"master"
  }
}

Normal response codes: 201
{
    "passid":"xxxxx",
    "local_git":"ssh://localhost/paasdata/confcenter/{paasid}/pdmng/.git"
}

Error response codes: 400
{
    "desc": "error reason"
}

提取下:

  • http 动作为:POST
  • URL 中需要传入参数 paasid
  • body 体为一个 json 体
  • 返回信息为两个:一个成功201、一个失败400,以及相应的返回值

在Swagger 中这样处理:

path:
  /api/v1.0/designer/paas/{paasid}:
    post:
      tags:
        - paas
      produce:
        - application/json
      parameters:
        - name: paasid
          type: string
          in: path
          required: true
        - name: gitinfo
          in: body
          required: true
          schema:
            properties:
              git:
                type: object
                required:
                  - addr
                  - branch
                properties:
                  addr:
                    type: string
                    description: git address
                  branch:
                    type: string
                    description: git branch
      response:
        201:
          description: create paas id success
          shcema:
            properties:
              paasid:
                type: string
                description: paasid
              local_git:
                type: string
                description: address in localhost
        400:
          description: create paas id failed
          schema:
            properties:
              error:
                type: string
                description: the reason of error

分解下,上文写配置文件实现的API:

  • url 信息:动作post, 以及响应类型:application/json
  • parameters: 处理的是传入的参数
  • responses: 处理的是响应的信息

逐步分析:

添加访问路径和http动作

paths:
  /api/v1.0/designer/paas/{paasid}:
    post:
      tags:
        - paas

即:POST: /api/v1.0/designer/paasid/{paasid}

添加处理信息

produces:
  - application/json

即:响应内容格式json

定义参数:URL 参数,和传入的参数

parameters:
  - name: paasid
    in: path
    description: create paasid
    required: true
    type: string
  - name: Gitinfo
    in: body
    description: git info of body
    required: true
    schema:
      properties:
        git:
          type: object
          required:
            - addr
            - branch
          properties:
            addr:
              type: string
            branch:
              type: string

即:url 中需要传入一个参数 paasid

同时body 体需要传入一个json 格式的参数

{
  "git": {
    "addr":"",
    "branch": ""
  }
}

上文:

  • schema 模式来描述具体的参数的信息:
    • type: 参数类型:integer, string, array, boolean等
    • in: 表示参数是在url 路径里,还是在body 里,或者是在请求里
    • description: 对参数的介绍
    • required: 表示是否一定需要该值,默认false

定义响应信息:状态码和响应值

即:状态码 201、400

响应信息也使用 schema 模式来描述具体的参数信息:

  • 嵌套处理 type : object
  • properties 属性值
  • type: 属性的类型
  • description: 属性的介绍

总结:编写配置文件,可视化API 的核心就是在处理path

  • 编写路径和动作
  • 定义参数
  • 定义响应信息

最终效果如下:

微信截图_20180130215708.png
微信截图_20180130214149.png

更多用法需要探讨,学习稍微有点成本,但都可以学会。

6. 参考文献

ChangeLog

  • 2018.01.29 成文
  • 2018.01.30 修订
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容