Date 一 22 五月 2017 By wuwenjie Category 工具. Tags dev-tools
He who has a "why" to live for can bear almost any "how" --尼采
此前一直在关注swagger,不过也一直处于看看案例,读读文档的状态。关于写api接口文档和mock的事,多次头疼,看了许多工具都不甚满意,最近在使用Mock(在线体验)的时候
发现它在文档里写道:
支持同步 Swagger 文档,1秒便能生成 Mock 数据。之后接口文档更新也能通过更新操作重新生成 Mock 数据
这太强大了,心动不已。
我自己很喜欢easy-mock这个工具,但写REST api的时候,感觉重复数据声明太多,很不爽,我们知道post/put的大部分属性是相同的,而get/post也有大量重复的属性。如何能以一种更加方便的方式在easy-mock(其他的mock工具也一样)定义接口,以便于更好地做到DRY
, Swagger是绝佳的解决方案,而且它能带给你的远不止于此
why的问题一解决,how to do 只是细节问题了
于是重新花了2个晚上的时间,集中地读了文档,也动手写了几个demo,很符合预期
接下来以经典的3w问题为线索来记录下我的学习过程
关于swagger是什么的问题,swagger的首页说的再清楚不过:
Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment.
因为swagger庞大的生态系统,我们在api的整个生命周期中都能从中受益: from design and documentation, to test and deployment
前头我的easy-mock属于test部分,同时它也有效地帮助前后端分离
如果你想对Swagger有更深的了解,可以看下对Tony Tam的这段采访(Tony Tam影响了Swagger的诞生):通过Swagger进行API设计,与Tony Tam的一次对话
上述这段引用中有一个名词值得一提:OpenAPI Specification(OAS)
,它本身开放在OpenAPI-Specification,它的目的是:
The goal of The OpenAPI Specification is to define a standard, language-agnostic interface to REST APIs
如果你在为一个系统设计API,你希望更好的管理你的API,你希望有一个工具能一站式地解决API相关的所有事情,从设计到文档再到mock,甚至能直接从设计文档中生成代码(声明式编程),这确实是可能的,如果你的描述信息是完备的,自动化生成mock接口,同时也可生成各种语言与api交互的SDK
这些便是你选择Swagger的理由
最后便是怎么做的问题,这反而不太难,在互联网高度发达的今天,海量的资料遍布网络
我接下来把我的学习过程和资料做个笔记,希望对你有用
尽管Swagger本身是开源的,你可以自行搭建整个工具链,但从在线工具开始尝试,会让你更快接触核心的东西,而不是在搭建工具上忙活半天
我们从swaggerhub开始
swaggerhub是个非常棒的项目,你在这里可以:
上边的截图是官方的demo:Swagger Petstore
,这是一个很完整的API项目(同时也比较复杂),我们可以一边试运行,一边做些修改看看每个参数的作用,如果你想对swagger的语法有个整体的认识,推荐这篇文档Swagger从入门到精通
我的做法是先通读一遍(粗读)上边的文档,之后对着别人的API项目学习,遇到不懂的去查阅这个文档
另外文档结尾处有个彩蛋:OpenAPI Specification Visual Documentation,这是查阅swagger写作语法的神器
Swagger生态极其庞大,各种工具层出不穷,如何确定一个清晰工作流。而不会在庞大的生态链里迷失
我觉得核心是理解:Swagger的生态系统是围绕Swagger文档(json/yaml)构建的,就是说我们书写的纯文本(json/yaml)便是我们输出的所有东西,它是全息的,我们手里只需有这个纯文本,就能做所有事情,此外的工具都是围绕它构建的,把这个纯文本导入到响应的工具里,就可获得其他功能,诸如漂亮的UI,自动化的mock等等
你熟悉markdown的话,你会发现他们在设计思路上有不少相似点
编写API文档,其实我们只是在写一个简单的纯文本文件。你可以用任何你喜欢的文本编辑器来写(vim/emacs/atom/vscode/sublime)。但是为了提高效率,建议选择Swagger Editor(swaggerhub默认是它),诸如语法检查之类的功能能帮你省下大量排错的时间
学习一个新技术,我喜欢用它写一个简单的blog,我们接下来试试用swagger来写博客文章的API,我们假设Article有四个属性:
API是RESTful风格(可以参考我此前的文章RESTful-Api),支持:
get /articles
: 获取文章列表post /articles
: 新建一篇文章(登录用户)get /articles/
: 获取文章详情(指定文章id)put /articles/
: 更新某篇的文章delete /articles/
: 删除某篇的文章get /articles/search?title=python
: 搜索文章下边是它的api描述
swagger: "2.0" info: version: 1.0.0 title: blog # description支持markdown description: | # blog API documentation 这篇文档描述了的blog(article)的api接口 # host: localhost:8000 #localhost blog # basePath: /api schemes: - https - http consumes: - application/json produces: - application/json paths: /: get: summary: Service root description: 列出所有api的描述信息. operationId: root responses: '200': description: Success security: [] /articles: get: summary: list all articles operationId: list_all_articles #后端函数 responses: '200': #todo description: Annotation successfully created schema: $ref: '#/definitions/ArticleList' '400': description: Could not create article from your request schema: $ref: '#/definitions/Error' post: summary: Create a new Article operationId: createArticle parameters: - name: Article in: body description: article to be created required: true schema: $ref: '#/definitions/NewArticle' responses: '200': description: article successfully created schema: $ref: '#/definitions/Article' '400': description: Could not create article from your request schema: $ref: '#/definitions/Error' /articles/{id}: get: summary: Fetch an Article operationId: fetchArticle parameters: - name: id in: path description: ID of article to return required: true type: string responses: '200': description: Success schema: $ref: '#/definitions/Article' '404': description: article not found or no permission to view schema: $ref: '#/definitions/Error' patch: summary: Update an Article description: | This endpoint is available under both the `PATCH` and `PUT` request methods. Both endpoints have PATCH-characteristics as defined in [RFC5789](https://tools.ietf.org/html/rfc5789#section-1), meaning the request body does not have to include the whole Article object. New implementations should use the `PATCH` request method, and existing implementations continue to work under `PUT` but should switch to `PATCH`. operationId: updateArticle parameters: - name: id in: path description: ID of article to return required: true type: string - name: Article in: body description: Updated article body required: true schema: $ref: '#/definitions/NewArticle' responses: '200': description: Success schema: $ref: '#/definitions/Article' '400': description: Could not create article from your request schema: $ref: '#/definitions/Error' '404': description: article not found or no permission to update schema: $ref: '#/definitions/Error' delete: summary: Delete an Article operationId: deleteArticle parameters: - name: id in: path description: ID of article to return required: true type: string responses: '200': description: Success schema: type: object required: - deleted - id properties: deleted: type: boolean enum: - true id: type: string '404': description: article not found or no permission to delete schema: $ref: '#/definitions/Error' /search: get: summary: Search for annotations operationId: search #后台对应的函数名 parameters: - name: limit in: query description: The maximum number of annotations to return. required: false type: integer minimum: 0 maximum: 200 default: 20 - name: offset in: query description: > The minimum number of initial annotations to skip. This is used for pagination. required: false type: integer default: 0 minimum: 0 - name: sort in: query description: The field by which annotations should be sorted. required: false type: string default: updated responses: '200': description: Search results schema: $ref: '#/definitions/SearchResults' definitions: NewArticle: # todo json 2 yaml: https://www.json2yaml.com/ # 也可以是在线的 #$ref: './schemas/annotation-schema.json' #https://h.readthedocs.io/en/latest/api/schemas/annotation-schema.json type: object properties: userid: type: string #"pattern": "^acct:.+$" title: type: string content: type: string tags: type: array items: type: string Article: allOf: - $ref: '#/definitions/NewArticle' # NewArticle属性展开在这里 - required: - id properties: id: type: string Error: type: object required: - status properties: status: type: string enum: - failure reason: type: string description: A human-readable description of the reason(s) for failure. SearchResults: #用作list type: object required: - rows - total properties: rows: type: array items: $ref: '#/definitions/Article' total: description: Total number of results matching query. type: integer ArticleList: #用作list type: object required: - rows - total properties: rows: type: array items: $ref: '#/definitions/Article' total: description: Total number of results matching query. type: integer # Added by API Auto Mocking Plugin host: virtserver.swaggerhub.com basePath: /pwnote/blog/1.0.0
如果你对其中的语法有所不解可以查阅: Swagger从入门到精通
我同时做了以下工作:
可以在github上搜swagger,会发现有许多相关项目,我列出几个我恰好看到或关注的
django-rest-swagger
Django REST Framework是写api的神器
配合django-rest-swagger更是如虎添翼
connexion
swagger可自动生成的20多种server代码,其中包括flask版本的,在flask的版本代码里,主要用到的就是connexion
connexion是一个漂亮的框架,用于在Python中实现API First方法,如果你对此有兴趣可以参考Crafting effective Microservices in Python
如果你想看一个带有数据库和真实后端的例子,可以参考:connexion/examples/sqlalchemy,这个例子让我们看到一个完整的项目:api的文档以及后端实现
ReDoc
我最近在使用的一个是ReDoc,有不少有名的项目在用它作为api文档的展示工具:
版权声明:自由转载-非商用-非衍生-保持署名