Fork me on GitHub

使用 API BluePrint 编写 RESTful 接口文档

目录

  1. 1. 前言
  2. 2. 环境配置
    1. 2.1. Atom 下载安装
    2. 2.2. Atom 插件下载配置
    3. 2.3. aglio 安装
  3. 3. API 文档编写
    1. 3.1. 新建文档
    2. 3.2. 编写 API 文档
      1. 3.2.1. 元数据 Metadata
      2. 3.2.2. API 名称和描述
      3. 3.2.3. 资源与资源组
    3. 3.3. 导出文档为HTML
  4. 4. 参考

前言

作为后台 RESTful 开发者,当完成了功能开发后,还有件事要做的是需要提供一个文档给调用者们。
那如何快速写出高大上的接口文档呢?在熟练使用 markdown 的情况下,当然是希望能用 markdown 的语法
来写。在这里介绍一下 API Blueprint ,它就是一个功能强大的高级别基于 markdown 的 Web API 描述语言。

API Blueprint. A powerful high-level API description language for web APIs.
API Blueprint is simple and accessible to everybody involved in the API lifecycle. Its syntax is concise yet expressive. With API Blueprint you can quickly design and prototype APIs to be created or document and test already deployed mission-critical APIs.

这里记录一下在 Mac 下使用 Atom 编辑器配合 Atom editor language 语法高亮,以及结合 aglio 进行渲染最终输出静态的 HTML 文件。

环境配置

Atom 下载安装

打开官网直接下载 dmg 文件,或者点这里进行下载,然后拖放到 应用程序目录下即可。

Atom 插件下载配置

  1. 打开下载好的 Atom 然后按快捷键Command+,打开Preferences,或者选择在顶部工具栏依次打开Atom->Preferences
    然后选择Install,在搜索栏里输入language-api-blueprint选择搜索Packages进行搜索,然后点击Install
    操作如下图:
    install package
  2. 插件下载安装完成后,点击language-api-blueprintSettings,然后勾选:

    • [x] Show Indent Guide 显示缩进,因为 API BluePrint 对缩进要求比较高,这个开着比较好,方便排错
    • [x] Show Invisibles 显示空格,Tab键,以及换行符。

    如下图:
    blueprint-settings

aglio 安装

aglio 依赖于 Node.js ,Node.js 安装请参考官网,使用 npm 命令安装:

1
2
# 提示权限拒绝时,需要使用 sudo
npm install -g aglio

疑问
有人可能会问为什么不用 atom 里面的 api-blueprint-preview 插件来预览,导出,而使用单独的 aglio,这里我已经尝试使用过 atom 里的 preview 插件,但是效果不是很好,而且导出会出现错误。而且不支持自定义主题。但 aglio 都能做到这些。

API 文档编写

这里使用 Node.js 开源技术社区的API:http://cnodejs.org/api
并编写一下接口文档:

  • 主题
    • 主题首页
    • 主题详情
    • 新建主题
  • 主题收藏
    • 收藏主题
    • 取消主题
    • 用户所收藏的主题
  • 评论
    • 新建评论
    • 为评论点赞

新建文档

打开 Atom Command + N新建一个标签页,然后保存为cnodejs-api.apib,文件扩展名apib是 API BluePrint 的缩写。

编写 API 文档

一个完整的 API BluePrint 文档要包括以下部分(带*为必须有):

  • Metadata section 元数据部分*
  • API name & overview section API 名称和说明部分*
  • Resource group section 资源组部分
  • Resource section 资源部分*
  • Resource model section 资源模型部分
  • Schema section
  • Action section 动作部分*
  • Request section 请求*
  • Response section 相应*
  • URI parameters section 请求 URL 参数
  • Attributes section 属性部分
  • Headers section HTTP Headers 部分
  • Body section HTTP Body 部分*

元数据 Metadata

1
2
FORMAT: 1A
HOST: http://cnodejs.org/api/v1/

这元数据区域的 key-values 是为了渲染工具定义的,如:

  • FORMAT: 1A是指明 API BluePrint 的版本,
  • HOST指明了这个api 的 HOST 部分,这里还加了api/v1部分,为下面写接口提供方便,不用每次都写这个前缀部分了。

API 名称和描述

#后面 写API 名称,紧接着换一行写 API 文档的说明就可以了。

1
2
# CNodejs API
欢迎使用 **CNodejs** API ,这些 API 提供了访问 **CNodejs** 基本的数据接口。

预览:
打开终端,cd 到cnodejs-api.apib同级目录,在终端中输入:

1
aglio -i cnodejs-api.apib -s

这时会提示:

1
2
Server started on http://127.0.0.1:3000/
Rendering cnodejs-api.apib

在浏览器里打开http://127.0.0.1:3000/就可以看到预览了。
preview

资源与资源组

这里的 CNodejs 第一个主题部分,主题下有三个资源,分别是:

  • 主题首页
  • 主题详情
  • 新建主题

现在来看看怎么用资源组来完成这三个接口文档的编写。
这三个接口都与主题相关,新建,查看详情,获取列表。这样我们通过组把这三个接口放到一起。

  1. 首先新建一个组:

    1
    2
    # Group 主题
    CNodejs 主题部分的资源集合

    需要注意的是,在#Group主题之间都有一个空格, API BluePrint 对格式控制比较高,如果
    不遵循它的格式,有可能出现渲染出来的不对。
    第一行是定义一个组,第二行是对这个组进行一些描述。

  2. 这里我们可以看到首页主题新建主题的 API URL 都一样,只有参数不太一样,这里就可以把这两个放在一起。
    一个完整的 API 请求,包括请求地址,请求参数,请求方法,请求响应,有的还会有请求头部Headers,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ## Topics [/topics]
    主题集合
    ### 首页主题 [GET]
    + Parameters
    + page: `1` (number,optional) - 页数
    ...
    + Response 200 (application/json)
    + Body
    {
    ...
    }
    ### 新建主题 [POST]
    + Parameters
    + page: `1` (number,optional) - 页数
    ...
    + Response 200 (application/json)
    + Body
    {
    ...
    }

    注意:##Topics[/topics]直接都留有一个空格。

    请求地址: /topics ,这个就是## Topics [/topics]里的[]中的值,##是继承于# Group 主题

    请求参数: 这里首页主题有 page,tab ,limit ,mdrender 四个参数,
    新建主题有 accesstoken ,title ,tab ,content 四个参数,
    两个加起来一共有 7 个参数,现在把这 7 个参数放到 ## Topics [/topics]后面,最终得到:
    ## Topics [/topics{?page,tab,limit,mdrender,accesstoken,title,content}]

    请求方法: GET,也就是### 首页主题 [GET]里的[]中的GET。同样###是继承于## Topics

    具体参数-首页主题: 参数的写法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    + param_name: `example-value` (type,[optional,required]) - 描述
    + page: `1` (number,optional) - 页数
    + tab: `ask` (string,optional) - 主题分类。目前有 ask share job good
    + Members
    + `ask`
    + `share`
    + `job`
    + `good`
    + limit: `10` (number,optional) - 每一页的主题数量
    + mdrender (string,optional) - 是否渲染出现的所有 markdown 格式+ 文本。
    + Default: `true`

    其中tab下还有 + Members这个是可选值,而mdrender下还有个Default这个表示参数的默认值

    请求响应: Response后面的 200 是服务器返回的 HTTP Response Code,(application/json)
    表示返回的Content-Typeapplication/json
    + Body是Response 的内容,这里返回了json

    最后: 得到完整的内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    ## Topics [/topics{?page,tab,limit,mdrender,accesstoken,title,content}]
    主题集合
    ### 首页主题 [GET]
    分页按类型获取首页主题列表
    + Parameters
    + page: `1` (number,optional) - 页数
    + tab: `ask` (string,optional) - 主题分类。目前有 ask share job good
    + Members
    + `ask`
    + `share`
    + `job`
    + `good`
    + limit: `10` (number,optional) - 每一页的主题数量
    + mdrender (string,optional) - 是否渲染出现的所有 markdown 格式+ 文本。
    + Default: `true`
    + Response 200 (application/json)
    + Body
    {
    "success": true,
    "data": [{
    "id": "57563b08c1326f410e9147f5",
    "author_id": "542bff0c10ab5791322617c7",
    "tab": "share",
    "content": "...省略了",
    "title": "Freecodecamp 第一回:端午节之约",
    "last_reply_at": "2016-06-08T01:05:03.911Z",
    "good": false,
    "top": true,
    "reply_count": 5,
    "visit_count": 678,
    "create_at": "2016-06-07T03:10:00.284Z",
    "author": {
    "loginname": "Samurais",
    "avatar_url": "https://avatars.githubusercontent.com/u/3538629?v=3&s=120"
    }
    }, {
    "id": "572afb6b15c24e592c16e1e6",
    "author_id": "504c28a2e2b845157708cb61",
    "tab": "share",
    "content": "...省略了",
    "title": "新的社区推荐客户端:Noder",
    "last_reply_at": "2016-06-07T14:47:00.183Z",
    "good": false,
    "top": true,
    "reply_count": 153,
    "visit_count": 15410,
    "create_at": "2016-05-05T07:51:07.576Z",
    "author": {
    "loginname": "alsotang",
    "avatar_url": "https://avatars.githubusercontent.com/u/1147375?v=3&s=120"
    }
    }, {
    "id": "5696e43e6272216e51bff67e",
    "author_id": "54009f5ccd66f2eb37190485",
    "tab": "share",
    "content": "<div class=\"markdown-text\">...省略了<p><img src=\"//dn-cnode.qbox.me/FtALxsauUkYDGdzcuA5y6BaIdUMC\" alt=\"node全栈.png\"></p>\n</div>",
    "title": "国内Nodejs 2015汇总",
    "last_reply_at": "2016-06-03T07:45:07.581Z",
    "good": true,
    "top": true,
    "reply_count": 118,
    "visit_count": 54347,
    "create_at": "2016-01-13T23:56:46.312Z",
    "author": {
    "loginname": "i5ting",
    "avatar_url": "https://avatars.githubusercontent.com/u/3118295?v=3&s=120"
    }
    }]
    }
    ### 新建主题 [POST]
    新建一个主题
    + Parameters
    + accesstoken (string) - 用户的 accessToken
    + title (string) - 标题
    + tab (string) 目前有 ask share job
    + Members
    + ask
    + share
    + job
    + content (string) - 主体内容
    + Response 200 (application/json)
    + Body
    {
    success: true,
    topic_id: '5433d5e4e737cbe96dcef312'
    }
  3. 主题详情,大概的结构和上面的差不多。

    1
    2
    3
    4
    5
    ## 主题详情 [GET /topic/{id}]
    根据`id`获取主题详情
    + Parameters
    + Response 200 (application/json)

    因为这个接口没有相类似的接口,这里直接将 HTTP GET 方法 和 请求 URL PATH 部分写在一起。而不用像上面两个接口那样分别写,简化方便。
    完整的内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    ## 主题详情 [GET /topic/{id}/{?mdrender,accesstoken}]
    根据`id`获取主题详情
    + Parameters
    + id: `a2d4fa` (string) - 主题ID
    + mdrender (string,optional) - 是否渲染出现的所有 markdown 格式文本。
    + Default: `true`
    + accesstoken (string,optional) - 当需要知道一个主题是否被特定用户收藏时,才需要带此参数。会影响返回值中的 `is_collect` 值。
    + Response 200 (application/json)
    + Body
    {
    "success": true,
    "data": {
    "id": "5433d5e4e737cbe96dcef312",
    "author_id": "504c28a2e2b845157708cb61",
    "tab": "share",
    "content": "省略了……",
    "title": "一个面向 Node.js 初学者的系列课程:node-lessons",
    "last_reply_at": "2015-04-12T12:36:58.320Z",
    "good": true,
    "top": false,
    "reply_count": 84,
    "visit_count": 21997,
    "create_at": "2014-10-07T12:00:36.270Z",
    "author": {
    "loginname": "alsotang",
    "avatar_url": "https://avatars.githubusercontent.com/u/1147375?v=3&s=120"
    },
    "replies": [{
    "id": "5433d866e737cbe96dcef313",
    "author": {
    "loginname": "leapon",
    "avatar_url": "https://avatars.githubusercontent.com/u/4295945?v=3&s=120"
    },
    "content": "<div class=\"markdown-text\"><p>我喜欢你的写作风格</p>\n</div>",
    "ups": ["5404a4120256839f712590f3", "50f3b267df9e9fcc58452224"],
    "create_at": "2014-10-07T12:11:18.981Z",
    "reply_id": null
    }, {
    "id": "5528eaa7831bc33a414106e2",
    "author": {
    "loginname": "jacksun90",
    "avatar_url": "https://avatars.githubusercontent.com/u/8536173?v=3&s=120"
    },
    "content": "<div class=\"markdown-text\"><p>还不错,先收录了\n自豪地采用 <a href=\"https://github.com/lanceli/cnodejs-ionic\">CNodeJS ionic</a></p>\n</div>",
    "ups": [],
    "create_at": "2015-04-11T09:34:31.464Z",
    "reply_id": null
    }],
    "is_collect": false
    }
    }

导出文档为HTML

打开终端,在终端中输入下面的命令:

aglio --theme-full-width -i cnodejs-api.apib -o cnodejs.html

这样就能够生成一个完整的高端大气好看的 API 文档了。效果看截图:
generated html

这里只介绍了比较简单的用法,还有很多高级用法看官方的文档吧。本文中的例子也放到了Gist上面,点这里查看

参考

本文总阅读量