歡迎光臨
每天分享高質量文章

如何編寫相對標準的後端專案(二)設計 Restful API

(點選上方公眾號,可快速關註)


來源:koala bear,

wsfdl.com/architecture/2018/01/18/http_restful_api_design.html

本文主要介紹 Restful 風格,如何設計 HTTP Restful API,以及在設計過程中的一點經驗之談。文章有點枯燥,敬請諒解。最後建議在設計 HTTP API 時,遵循 Restful API 風格。

理解 Restful Style

在 web 飛速發展的環境下,Roy Fielding 於 2000 年在博士論文 Architectural Styles and the Design of Network-based Software Architectures 提出 REpresentational State Transfer (REST) 概念,它倡導一種新的 web 架構風格,具有面向資源、松耦合、無狀態、易擴充套件等特點,如今被廣泛的應用。

那麼什麼是 REST 風格呢,論文的第五章節 Representational State Transfer (REST) 做了詳細說明,其中 uniform interface 是 REST 架構的最主要特徵。

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components…….

In order to obtain a uniform interface, multiple architectural constraints are needed to guide the behavior of components. REST is defined by four interface constraints: identification of resources; manipulation of resources through representations; self-descriptive messages; and, hypermedia as the engine of application state.

註意前兩個約束:identification of resources 和 manipulation of resources through representations,它們表明 uniform interface(即 RESTful API) 的主體是 resource,即 REST 是面向 resource 的。那麼什麼是 resource 呢?任何能夠被命名的事物都可稱為 resource,比如某個文字、影象,甚至某種服務。在 web 中,我們採用 URI 來指代某個 resource。顧名思義,representation 就是資源的表現形式,比如影象資源的表現形式可為 JPEG image,文字資源的表現可為 text。

那麼第三個約束 self-descriptive messages 表示什麼呢?論文是這樣解釋的,即採用 standard methods(如 HTTP Method) 和 media types(如 HTTP Content type) 來表示操作型別,舉例來說,我們可以用 GET 方法表示查詢某個資源,用 DELETE 方法表示刪除某個資源。

第四個約束 hypermedia as the engine of application state 表示 application 的狀態由 request 決定,即客戶端透過傳送 request 來改變 application 的狀態。以 HTTP POST 為例,客戶端可以新建一個 resource,因而改變了 application 的狀態。

總結而言,uniform interface 的約束條件定義了 web application API 的風格,即 RESTful API,這種 API 是面向 resource 的,利用(HTTP)標準方法來描述操作,客戶端透過 representation 來操作 resource,從而轉化 resource 的狀態。

推薦閱讀

  • Architectural Styles and the Design of Network-based Software Architectures

如何設計 Restful API

上節簡單的介紹了 Restful 的核心特徵,本文從實踐角度出發,圍繞 URI,HTTP Method,Response Code,序列化和安全等,並結合一個具體的案例,談談 Http Restful API 設計的經驗。

比如某個賬號系統(http://example.com),通常需要增刪改查使用者,我們就以增刪改查使用者(user)為例,詳細的介紹Restful API 的設計。

URI 設計

作為 Restful 的核心特性,uniform interface 是面向資源的,我們用 URI 來指代某個資源。比如,我們用如下 URI 代表賬號系統使用者 john:

http://example.com/users/john

為了簡便,後續例子可能會省略域名,用 /users/john 表達相同含義。

查詢使用者 john 的請求如下。

GET /users/john

更新使用者 john 的請求如下。

PUT /users/john

刪除使用者 john 的請求如下。

DELETE /users/john

從上可以看出,不論是查詢還是刪除使用者 john,我們都用相同的 URI 來表指代這個使用者(資源),採用不同的 Http Method 來表示不同的操作型別。既然 /users/john 指代的是使用者 john,顧名思義,/users 指代的是所有的使用者,所以可以用如下請求查詢所有的使用者資訊。

GET /users

因為 URI 代表的是某個資源,而資源本身是個名詞,所以在設計 URI 時,也應該用名詞,切記不要使用動詞等詞語。比如,如下 URI 是面向動作的,不滿足 Restful 風格約束。

/users/getuser

帳戶系統在不同階段可能會有不同的版本,比如 v1,v2,我們通常把版本號放在前面,比如:

/v1/users/john /v2/users/john

如果需要查詢某些符合要求的資源,可在 URI 的 paras 模組設定查詢引數,如查詢所有性別為女的使用者

GET /users?gender=female

如果傳回結果過多,可以加上分頁功能,如查詢自 john 起的 10 位使用者。

GET /users?limit=10▮=john

此外,在設計 uri 時,還應該註意如下要點:

  • 儘量用小寫:比如用 john,最好不要用 John。

  • 用中槓 -,不用下槓 _

HTTP Method

HTTP 協議定義了 8 個 Method,在 Restful API 設計中,我們常用 POST,DELETE,PUT,GET 四方法來操作資源。其中 POST 表示建立資源,DELETE 表示刪除某個資源,PUT 表示更新某個資源,GET 表示查詢資源。例如,當我們要建立使用者 andy 時,其 API 如下:

POST /uesrs Body: {“user”: “andy”, …}

在設計 Restful API 時,應該遵循 HTTP 關於 “安全性” 和 “冪等性” 的要求。

  • 安全性:無論請求多少次,都不會改變資源的狀態。比如 GET 操作,無論執行多少遍,都不會改變資源的狀態。所以對於 GET 類 API,在編寫應用端程式碼時,切記要盡可能避免出現刪除或者更新資料的邏輯。

  • 冪等性:無論是執行一次,還是執行多次,效果是等價的,比如 DELETE,PUT 操作。以 DELETE 操作為例,刪一次和刪多次,效果都是該資源不存在了。

在 HTTP 協議,不同 Method 在 “是否有 request body” 和 “是否有 response body” 有所差異。總結如下表:

Response Code

之所以著重談談 Response Code,是因為看到部分同學在設計 API 的時候,常常自己定義 Response Code。例如,查詢某個不存在的使用者 tom 時,其 Response 為:

GET /users/tom Response Code: 200 OK Body: {“error”: {“message”: “User tom not found.”, “code”: 100}}

在上述查詢某個不存在的資源的例子中,其 Response Code 為 200,此外,還在 Body 中定義了代號為 100 的傳回碼。事實上,這種做法非常容易給使用者造成困惑:首先,200 表示查詢成功,而本例的查詢結果卻是失敗的;再次,自定義的 100 的含義是什麼?如果沒有相關說明檔案,使用者是不得而知的。所以,清晰明瞭的傳回值應該設計為如下:

Response Code: 404 Not Found Body: {“error”: {“message”: “User tom not found.”}}

設計 API 時,請先深入理解 HTTP Response Code,充分利用它們代表的含義,除非特別需要,儘量不要去自己定義額外的傳回碼,以免引起誤解。讓我們一起回顧下常見 HTTP Response Code 的含義。

請求成功:

  • 200 OK: 請求已成功,Body 有傳回內容。多用作 GET Method 的 API 的傳回碼。

  • 201 Created: 請求已經被實現,資源被建立。多用作 POST Method 的同步型別 API 的傳回碼。

  • 202 Accepted: 伺服器已接受請求,但尚未處理。多用作 POST Method 非同步型別 API 的傳回碼。

  • 204 No Content: 伺服器成功處理了請求,沒有傳回任何內容。用多於 DELETE/PUT Method 的 API 的傳回碼。

因客戶端原因導致請求失敗:

  • 400 Bad Request: 如引數錯誤,格式錯誤

  • 401 Unauthorized: 使用者未被認證,如用密碼錯誤,證書錯誤

  • 403 Forbidden: 使用者許可權不夠

  • 404 Not Found: 服務端無此資源。通常為 URL 不存在,或者某個 Method 不存在

  • 409 Conflict: 請求存在衝突無法處理該請求

因服務端原因導致請求失敗:

  • 500 Internal Server Error: 服務端錯誤訊息,伺服器遇到了一個未曾預料的狀況。這是最常用的服務端錯誤程式碼

  • 501 Not Implemented: 伺服器不支援當前請求所需要的某個功能

  • 503 Service Unavailable: 如伺服器維護或者過載等

編碼

ASCII 編碼計算機最早採用的字元編碼,隨著計算機在多個國家普及,幾乎每個語言都有一套或者多套自己的編碼 ,如漢字的 GBK 編碼,日語的 Shift_JIS 編碼。這些編碼方案各不相同,非常容易造成相容性問題。Unicode 的誕生很好的解決了上述問題,它使計算機能夠跨語言、跨平臺進行文字轉換和處理。Unicode 字符集包含了世界上所有文字和符號,它有 utf-8,utf-16 等編碼方案,其中 utf-8 是最為常用的編碼方案。從個人經驗而言,除非有特殊要求:

從 API 入口,到業務邏輯處理,再到儲存,一律使用 utf-8 編碼!

從 API 入口,到業務邏輯處理,再到儲存,一律使用 utf-8 編碼!

從 API 入口,到業務邏輯處理,再到儲存,一律使用 utf-8 編碼!

 

如果要支援 emoji 表情,還需額外的處理。

在 HTTP 協議中,Accept-Charset/Content-Type 頭部可以指定字元編碼方案。

  • Requst 頭部: Accept-Charset: utf-8

  • Response 頭部: Content-Type: charset=utf-8

序列化

在通訊過程中,我們常常需要把應用層的物件轉換成一段連續的二進位制串,或者反過來,把二進位制串轉換成應用層的物件——這兩個功能就是序列化和反序列化。XML/SOAP/JSON 等都是序列化和反序列化協議,其中 XML 多用於 html 型別的應用,而 JSON 成為 html 應用以外的主流序列化和反序列化協議。從個人經驗而言,除非特殊需要,建議:

採用 JSON 作為序列化和反序列化協議,對於 html 型別應用,使用 XML。

在 HTTP 協議中,Accept/Content-Type 頭部可以指定序列化和反序列化協議。

  • Requst 頭部: Accept: application/json

  • Response 頭部: Content-Type: application/json

HTTPS

出於安全的因素,此處普及下 HTTPS。HTTPS 由網景公司建立,基於 SSL(Secure Socket Layer) 或 TLS(Transport Layer Security),它作用有兩點:一是建立一個資訊保安通道,保障報文在各類通道中安全的傳輸;二是保證網站的真實性。

HTTPS 預設的埠是 443,如果採用預設埠,可以省略 443。例如:

https://example.com/users/john

一般來說,常見的 HTTP Server 都支援 HTTPS 功能,經過簡單的配置即可支援 HTTPS。對開發者來說,你需要:

  • 選擇支援 HTTPS 協議的 Web Server

  • 知道如何配置證書。

機構頒發的證書一般需要萬把塊錢購買;你也可以使用 openssl 自己製作證書。如果你對 HTTPS 原理感興趣,建議瞭解下 RSA/DH 演演算法,對稱加密/非對稱加密,數字簽名,還有證書的含義和原理。

推薦閱讀

  • HTTP Method

    https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7/

  • 跟著 Github 學習 Restful HTTP API 設計

    http://cizixs.com/2016/12/12/restful-api-design-guide

  • Learn REST: A RESTful Tutorial

    http://www.restapitutorial.com/

  • HTTP 權威指南

看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,看技術乾貨

贊(0)

分享創造快樂