使用swagger 生成 Flask RESTful API

什麼是 RESTful

什麼是REST

REST(英文:Representational State Transfer,又稱具象狀態傳輸)是Roy Thomas Fielding博士於2000年在他的博士論文 中提出來的一種萬維網軟件架構風格,目的是便於不一樣軟件/程序在網絡(例如互聯網)中互相傳遞信息。html

REST 的核心是可編輯的資源及其集合,用符合 Atom 文檔標準的 Feed 和 Entry 表示。每一個資源或者集合有一個唯一的 URI。系統以資源爲中心,構建並提供一系列的 Web 服務。python

在 REST 中,開發人員顯式地使用 HTTP 方法,對系統資源進行建立、讀取、更新和刪除的操做:git

  • 使用 POST 方法在服務器上建立資源
  • 使用 GET 方法從服務器檢索某個資源或者資源集合
  • 使用 PUT 方法對服務器的現有資源進行更新
  • 使用 DELETE 方法刪除服務器的某個資源

若是一個架構符合REST原則,就能夠稱它爲RESTful架構github

RESTful API 設計定義

如下是幾個RESTful API的幾個概念。web

  • 資源(Resource):系統上的全部事物都被抽象爲資源(一篇文章,一張照片,一段語音)
  • 集合(Collection):一組資源的合輯稱爲集合(幾篇文章,幾張照片)
  • 路徑(Endpoint):路徑又稱」終點「,表示API的具體網址(每一個網址表明一種資源)

那麼一個設計良好的RESTful API應該遵循哪些原則呢?數據庫

協議

API與用戶的通訊協議老是使用HTTPs協議。編程

域名

應該儘可能將API部署在專用域名,例如:json

https://apis.gusibi.com複製代碼
API地址和版本

在url中指定API版本。好比:flask

https://apis.gusibi.com/v1複製代碼
以資源爲中心設計URL

資源是RESTful API的核心元素,全部的操做都是針對特定資源進化的。而資源就是URL表示的,因此簡潔、清晰、結構化的URL設計是相當重要的。
在RESTful 架構中,每一個網址表明一種資源(resource),因此網址中不能有動詞,只能有名詞,並且所用的名詞每每與數據庫的表格名對應。咱們來看一下 Github 的例子:api

/users/:username/repos
/users/:org/repos
/repos/:owner/:repo
/repos/:owner/:repo/tags
/repos/:owner/:repo/branches/:branch複製代碼
使用正確的Method

對於資源的具體操做類型,使用HTTP method 表示。
如下是經常使用的HTTP方法。

  • GET:從服務器取出資源
  • POST:在服務器新建一個資源
  • PUT:在服務器更新資源(客戶端提供改變後的完整資源
  • PATCH:在服務器更新資源(客戶端只提供改變了屬性)
  • DELETE:從服務器刪除資源

仍是使用 github 的例子:

GET /repos/:owner/:repo/issues
GET /repos/:owner/:repo/issues/:number
POST /repos/:owner/:repo/issues
PATCH /repos/:owner/:repo/issues/:number
DELETE /repos/:owner/:repo複製代碼
正確的過濾信息(filtering)

若是記錄數量不少,服務器不能都將他們返回給用戶。API應該提供參數,過濾返回結果。

下邊是一些是、常見的參數。

  • ?limit=10: 指定返回記錄的數量
  • ?offset=10:指定返回記錄的開始位置
  • ?page=2&per_page=100::指定第幾頁,以及每頁的記錄數。
  • ?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序。
  • ?animal_type_id=1:指定篩選條件
選擇合適的狀態碼

HTTP 應答中,須要帶一個很重要的字段:status code。它說明了請求的大體狀況,是否正常完成、須要進一步處理、出現了什麼錯誤,對於客戶端很是重要。狀態碼都是三位的整數,大概分紅了幾個區間:

2XX:請求正常處理並返回
3XX:重定向,請求的資源位置發生變化
4XX:客戶端發送的請求有錯誤
5XX:服務器端錯誤

常見的狀態碼有如下幾種:

200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
204 NO CONTENT - [DELETE]:用戶刪除數據成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
401 Unauthorized - []:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [
] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。
404 NOT FOUND - []:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。
422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。
500 INTERNAL SERVER ERROR - [
]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。

返回結果

針對不一樣操做,服務器向用戶返回的結果應該符合如下規範。

GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔

錯誤處理(Error handling)

若是出錯的話,在response body 中經過 message 給出明確的信息。若是狀態碼是4xx,就應該向用戶返回出錯信息。

良好的文檔

文檔應該是規範的API的重要的組成部分,沒有文檔的API是難以給他人使用的,也是不利於維護的。

其它
  • 使用 OAuth2.0 鑑權
  • 儘可能使用JSON做爲返回的數據格式
  • 限流

對應上述規則,咱們並不能保證其它的API提供者也會遵照,特別是文檔,有很大一部分API提供者給出的文檔是pdf或者word文檔,這是由於在API的迭代開發過程當中,文檔更新會比較麻煩。

swagger幫API使用者和開發者糾正了這個問題。

什麼是swagger

Swagger是一個簡單但功能強大的API表達工具。改框架爲建立JSON或YAML格式的RESTful API 文檔提供了OpenAPI規範。swagger文檔可由各類編程語言處理,能夠在軟件開發週期中嵌入源代碼控制系統中,以便進行版本管理。使用Swagger生成API,咱們能夠獲得交互式文檔,自動生成代碼的SDK以及API的發現特性等。

如何編寫API文檔

咱們能夠選擇使用JSON或者YAML來編寫API文檔。文檔示例以下:

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"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}複製代碼

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複製代碼

能夠發現,yaml格式的文檔比json格式的更清晰,可讀性更高,推薦使用yaml格式書寫文檔。

swagger 官網提供了 swagger editor: http://editor.swagger.io/#/,你能夠在這個編輯器中建立或導入文檔,並在交互式環境中瀏覽它。

如下是您導入 leads.yaml 定義後的 Swagger Editor UI 外觀:

Swagger Editor UI 外觀
Swagger Editor UI 外觀

右側的顯示窗格顯示了格式化的文檔,反映了在左側窗格中的代碼編輯器中執行的更改。代碼編輯器會指出了全部格式錯誤。你能夠展開和摺疊每一個窗格。

API文檔的基本結構

我用一個例子來介紹下swagger文檔的基本結構,這裏我用yaml格式來編寫文檔:

swagger: "2.0"
info:
 title: Sample API
 description: API description in Markdown.
 version: 1.0.0

host: api.example.com
basePath: /v1
schemes:
 - https

paths:
  /users:
 get:
 summary: Returns a list of users.
 description: Optional extended description in Markdown.
 produces:
 - application/json
 responses:
        200:
 description: OK複製代碼

上述文檔包括元數據(Metadata)、Base URL、API路徑(paths)三部分:

Metadata

這部分信息包括swagger 使用的版本:

swagger: "2.0"複製代碼

API相關的描述信息(好比API介紹、版本等):

info:
 title: Sample API
 description: API description in Markdown.
 version: 1.0.0複製代碼

Base URL

做爲web API,一個很重要的信息就是用來給用戶使用的 根URL,可用協議(http/https)、host地址:

host: api.example.com
basePath: /v1
schemes:
 - https複製代碼

全部的API都是base URL 的相對路徑 例如 /users 的API地址是 https://api.example.com/v1/users

路徑(Paths)

paths 部分定義API的路徑(endpoint)、支持的HTTP 請求方法

paths:  # 聲明路徑
  /users:  # 定義API路徑
 get:   # 定義請求方式
 summary: Returns a list of users.  # 簡介
 description: Optional extended description in Markdown.  # 描述
 produces:
 - application/json    # 定義 服務端response MIME types 
 responses:
        200:    # response 狀態碼
 description: OK複製代碼

固然這只是個最簡單的例子,swagger可定義的內容要比我提到的多的多。
具體詳細信息能夠看下 swagger 文檔:https://swagger.io/docs/specification/what-is-swagger/

固然,寫完文檔並不表明咱們的代碼就能夠直接使用這份文檔以及文檔中的約束,swagger 還提供了 swagger-codegen:https://github.com/swagger-api/swagger-codegen

swagger_codegen

swagger-codegen 是一個開源的代碼生成工具,它包含一個模板驅動引擎,能夠直接從咱們定義的 swagger 文檔中生成可視化的文檔查看界面和API客戶端。

這是一個開源的項目,地址是swagger-codegens: https://github.com/swagger-api/swagger-codegen。能夠本身安裝使用一下。

由於我最經常使用的語言是Python,因此給你們介紹一個第三方的 python 的代碼生成器swagger-py-codegen:https://github.com/guokr/swagger-py-codegen

swagger_py_codegen

swagger-py-codegen的亮點是它是一個Python web framework 代碼生成器,能夠根據swagger 文檔自動生成相應web framework 的代碼,如今支持 Flask, Tornado,falcon,最新版將支持sanic。

安裝

可使用 pip 安裝:

pip install swagger-py-codegen複製代碼

使用

安裝後使用命令以下:

swagger_py_codegen --swagger-doc api.yml example-app複製代碼

可選參數有:

-s, --swagger, --swagger-doc    Swagger doc file.  [required]
-f, --force                     Force overwrite.
-p, --package                   Package name / application name.
-t, --template-dir              Path of your custom templates directory.
--spec, --specification         Generate online specification json response.
--ui                            Generate swagger ui.
-j, --jobs INTEGER              Parallel jobs for processing.
-tlp, --templates               gen flask/tornado/falcon templates, default flask.
--version                       Show current version.
--help                          Show this message and exit.複製代碼

若是不指定 -tlp 參數,默認使用 flask 做爲模板。
若是指定 --ui --spec 參數則會在 由-p 參數指定的目錄下生成swagger UI 目錄 static。

舉個例子

咱們這裏使用 swagger-py-codegen 提供的測試文檔 執行:

swagger_py_codegen --swagger-doc api.yml example-app --ui --spec複製代碼

生成的代碼目錄結構以下

$tree
.
|__ api.yml

$ swagger_py_codegen -s api.yml example-app -p demo
$ tree (flask-demo)
.
|__ api.yml
|__ example-app
   |__ demo
   |  |__ __init__.py
   |  |__ v1
   |     |__ api
   |     |  |__ __init__.py
   |     |  |__ oauth_auth_approach_approach.py
   |     |  |__ oauth_auth_approach.py
   |     |  |__ users_token.py
   |     |  |__ users_current.py
   |     |  |__ users.py
   |     |__ __init__.py
   |     |__ routes.py
   |     |__ schemas.py
   |     |__ validators.py
   |__ requirements.txt複製代碼

能夠看到,這時一個簡單的app框架已經生成了,其中 routes.py 是自動生成的路由,validators.py 是response和request的校驗代碼,schemas.py 是由文檔生成的校驗規則,api 目錄下的各個文件是你定義的endpoint。

這時運行demo 目錄下的 __init__.py 文件:

python __init__.py複製代碼

會發現 server 已經啓動:

server 啓動示例
server 啓動示例

若是生成命令帶上 --ui --spec,生成代碼的同時也會生成swagger UI:

swagger_py_codegen --swagger-doc api.yml example-app --ui --spec複製代碼

啓動server後在瀏覽器輸入地址 http://0.0.0.0:8000/static/swagger-ui/index.html#!/default/get_users_uid

能夠看到直接使用的 swagger UI。

swagger ui 截圖
swagger ui 截圖

swagger-py-codegen 認證默認使用 OAuth2 認證方式,認證部分代碼須要本身實現。

如今代碼結構已經生成,能夠安心的寫邏輯代碼了。

總結

這一篇主要介紹了RESTful API以及如何使用swagger編寫規範的RESTful API。
最後介紹瞭如何使用 swagger-py-codegen 生成 web framework 的結構代碼。
參考連接中的文章都很是值得一看,建議都看一下。

參考連接


最後,感謝女友支持。

歡迎關注(April_Louisa) 請我喝芬達
歡迎關注
歡迎關注
請我喝芬達
請我喝芬達
相關文章
相關標籤/搜索