1. 程式人生 > >restful設計風格-使用swagger 生成 Flask RESTful API

restful設計風格-使用swagger 生成 Flask RESTful API

什麼是 RESTful

什麼是REST REST(英文:Representational State Transfer,又稱具象狀態傳輸)。

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

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

GET:從伺服器取出資源

POST:在伺服器新建一個資源

PUT:在伺服器更新資源(客戶端提供改變後的完整資源)

PATCH:在伺服器更新資源(客戶端只提供改變了屬性)

DELETE:從伺服器刪除資源

如果一個架構符合REST原則,就可以稱它為RESTful架構。

RESTful API 設計定義 以下是幾個RESTful API的幾個概念。

資源(Resource):系統上的所有事物都被抽象為資源(一篇文章,一張照片,一段語音)

集合(Collection):一組資源的合輯稱為集合(幾篇文章,幾張照片)

路徑(Endpoint):路徑又稱”終點“,表示API的具體網址(每個網址代表一種資源)

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

協議 API與使用者的通訊協議總是使用HTTPs協議。

以資源為中心設計URL 資源是RESTful API的核心元素,所有的操作都是針對特定資源進化的。而資源就是URL表示的,所以簡潔、清晰、結構化的URL設計是至關重要的。

在RESTful 架構中,每個網址代表一種資源(resource),所以網址中不能有動詞,只能有名詞,而且所用的名詞往往與資料庫的表格名對應。我們來看一下 Github 的例子:

/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 外觀

右側的顯示窗格顯示了格式化的文件,反映了在左側窗格中的程式碼編輯器中執行的更改。程式碼編輯器會指出了所有格式錯誤。你可以展開和摺疊每個窗格。

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_codegen swagger-codegen 是一個開源的程式碼生成工具,它包含一個模板驅動引擎,可以直接從我們定義的 swagger 文件中生成視覺化的文件檢視介面和API客戶端。

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

swaggerpycodegensapi.ymlexampleapppdemo 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 啟動示例

如果生成命令帶上 –ui –spec,生成程式碼的同時也會生成swagger UI:

可以看到直接使用的 swagger UI。

swagger ui 截圖

swagger-py-codegen 認證預設使用 OAuth2 認證方式,認證部分程式碼需要自己實現。

現在程式碼結構已經生成,可以安心的寫邏輯程式碼了。

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