随着见闻的逐渐加深,接触或者了解过一些其他的优秀的文档编写工具,由于未深入研究过,所以,仅仅在这里进行简单的列举:
swagger特点 swagger是我见过唯一还算将就的一个API文档制作与展示工具,其实最终都没让我找到一款完美的API文档编写工具。
swagger优点:
只针对API,而不针对特定的语言的API,很多自动生成API的工具基本都是只针对特定的API的
支持Json和yaml来编写API文档,并且支持导出为json、yaml、markdown等格式
如果编写好了API了,可以自动生成相应的SDK,没错,可能你的API接口代码还没有开始写,它就能帮你制作相应的SDK了,而且支持几乎所有主流编程语言的SDK
支持自动生成大量主流编程语言/框架的server端
界面清晰,无论是editor的实时展示还是ui的展示都十分人性化,其他的API编写工具基本上都做不到这一点,如果自己仅仅用markdown来编写,又要纠结该如何展现,十分痛苦。
官网有直接的demo,甚至都可以不用自己搞一套服务器
swagger缺点:
貌似无法更改主题
中英文的文档都比较少,其主要原因应该是官网的文档本身就不完善,只有针对不同模块儿的介绍,却没有针对具体用户的文档
yaml文件只能和API项目本身放在一起,这一点暂时还不知道有什么解决方案
其他的API文档编写工具 Apizza
外观模仿postman,但是只有网页版,必须谷歌浏览器并且必须安装插件,不开源,不能确定以后是否收费
由于外观模仿postman,所以ui上还是不大满意
能够自定义环境变量,并且可以不同的环境不同的环境变量
拥有团队协作功能,并且有一定的权限管理功能
可直接在接口处编写文档,并且能够导出HTML文档,导入Postman Json或者Swagger Json
偶尔会有缓存没有清理的问题
没有mock server的功能
APIBlueprint
自定义markdown语法,用markdown来编写
由于自定义了太多的语法,个人认为最后的markdown文件非常混乱,因为很多时候多空格多空行不会影响结果
也能生成mock server
界面美观,但是不是很直观
能够导出markdown和yaml
RAP
淘宝出品,Github上start数4000+
可以在公司内部搭建,不同的团队都可以在上面创建团队文档和分组
不能定义GET、POST、PUT、DELETE之外的请求
Model不能共享,写了一个地方另外一个地方还要写
只能定义200的响应,无法定义请求头、请求格式和相应格式
网页直接用js生成mock数据
界面有些地方好看,有些地方很丑。。。
只能导出为没有样式的html
安装与使用 我这里仅仅是简单地使用了swagger其中一项功能,即用swagger-editor
编写API文档,生成yaml文件,然后通过swagger-ui
来进行展示。由于仅仅是我本地搭建,所以两个组件都使用的docker搭建:
1 2 docker run -i -t -p 8080:8080 --name swagger-ui -d swaggerapi/swagger-ui docker run -i -t -p 8081:8080 --name swagger-editor -d swaggerapi/swagger-editor
然后访问http://127.0.0.1:8080
即可访问swagger-ui
,http://127.0.0.1:8081
即可访问swagger-editor
了。
接下来就是问题最多的如何使用的问题了,在第一次使用过程中,有诸多的问题需要解决,当然,主要的就是CROS问题。
CROS跨域问题 在使用editor的时候你可能会用到Try this operation
功能,即把接口定义好,想要直接进行请求调试,填上参数后网页可能会在js报这样的错误: XMLHttpRequest cannot load http://api.haofly.net/projects/test. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8081' is therefore not allowed access.
这就是传说中的CROS问题了,原因是后台程序为了安全默认关闭了跨域的请求,这时候有两种方式,一种是修改nginx,使其能直接通过,一种是修改程序,使其在返回请求的时候能够附带加上CROS的信息。例如,我在Laravel下面,可以添加这样一个中间件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 namespace App \Http \Middleware ;use Closure ;class EnableCrossRequestMiddleware { public function handle ($request , Closure $next ) { $response = $next ($request ); $response ->headers->set ('Access-Control-Allow-Origin' , 'http://127.0.0.1:8081' ); $response ->headers->set ('Access-Control-Allow-Headers' , 'Origin, Content-Type, Cookie, Accept, Authorization, Application, X-Requested-With' ); $response ->headers->set ('Access-Control-Allow-Methods' , 'GET, POST, PATCH, PUT, OPTIONS, DELETE' ); $response ->headers->set ('Access-Control-Allow-Credentials' , 'true' ); return $response ; } }
这样,后台程序就允许127.0.0.1:8081
这个域进行跨域访问了。
OAuth2认证问题 swagger是无法自定义请求头的,这一点,其Github上面的Issues有解释,现在已经忘了,但是针对特殊的头,它还是会有特定的办法,比如OAuth2的认证,它本身就是支持的。
首先,需要在yaml文件中定义这样一些字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 securityDefinitions: Bearer: type: apiKey name: Authorization in: header /projects/{projectName}: get: summary: 获取指定项目名的项目信息 security: - Bearer: [] parameters: - name: projectName in: path type: string description: 项目名 required: true responses: 200: description: 项目信息
之后,swagger-editor
实时预览会出现Security Authentication
的安全认证,可以将token
填入其中,然后在Try this operation
的时候勾选上Security->Bearer
即可,可以看到自动在请求头中添加了Authorization
字段了。
Swagger-ui获取解析文件的问题 其实Swagger-ui
仅仅是接收一个url,通过该url获取yaml文件,然后负责解析而已。但是,这里的坑也是不少的。
首先,在swagger-ui
中,默认发送的请求,是针对那个yaml文件所在的地方,这是十分坑的地方,所以yaml文件必须放在相应的API项目的文件里。暂时没有发现其他的解决方案。
其次,给定的url并不直接指向该文件的静态路径,而是需要添加CROS的响应头,所以不能直接用nginx的静态文件来处理。哎,所以基本上要做到的是,你直接访问那个url的时候,浏览器会弹出下载狂而不是直接显示那个文件的内容。
文档编写语法 虽然json
比yaml
好用,但是在这里我还是觉得yaml
更好看,更方便,所以我这里都用yaml
来用,并且如果要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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 swagger: '2.0' info: title: 文档标题 description: 描述 version: "v1.0" termsOfService: "" contact: name: "" url: "" email: "" license: name: "" url: "" host: api.haofly.net basePath: / schemes: - http - https securityDefinitions: api_key: type: apiKey name: Authorization in: header OauthSecurity: type: oauth2 flow: accessCode authorizationUrl: 'https://oauth.simple.api/authorization' tokenUrl: 'https://oauth.simple.api/token' scopes: admin: Admin scope user: User scope media: Media scope auth: type: oauth2 description: "" authorizationUrl: http://haofly.net/api/oauth/ name: Authorization tokenUrl: flow: implicit scopes: write:post: 修改文件 read:post: 读取文章 security: auth: - write:pets - read:pets consumes: - application/json - application/vnd.github.v3+json produces: - application/vnd.knight.v1+json - text/plain; charset=utf-8 tags: - name: post description: 关于post的接口 externalDocs: description: find more info here url: https://haofly.net paths: /projects/{projectName}: get: tags: - post summary: 接口描述 description: externalDocs: description: url: operationId: "" consumes: [string ] produces: [string ] schemes: [string ] deprecated: false security: - auth: - write:post - read: read parameters: - name: projectName in: path type: string allowEmptyValue: boolean description: 项目名 required: true default: * maximum: number exclusiveMaximum: boolean minimum: number exclusiveMinimum: boolean maxLength: integer minLength: integer enum: [* ] items: - $ref: "#/parameters/uuidParam" responses: 200: description: Success schema: $ref: '#/definitions/ProjectDataResponse' /another: responses: 200: description: schema: type: object properitis: data: $ref: '#/definitions/User' definitions: Product: type: object properties: product_id: type: integer description: product_name: type: string description: ProjectDataResponse: type: object properties: data: $ref: '#/definitions/ProjectResponse' parameters: limitParam: name: limit in: query description: max records to return required: true type: integer format: int32 responses: NotFound: description: Entity not found.
支持的数据类型 1 2 3 4 5 6 7 8 9 10 11 integer: int32 long: int64 float double string byte binary boolean date dateTime password