前端要知道的RESTful API架構風格

  • 2019 年 12 月 27 日
  • 筆記

前端程式設計師在開發完頁面後總是要對介面的,跟後端聯調有時候還佔用蠻大的時間的,那麼你了解你和後端對的介面都是什麼風格嗎,你們公司介面設計的如何,你使用愉快嗎?自己在寫Node服務時你遇到如何定義好介面的問題嗎?下面介紹一種API架構風格,也是目前主流的API設計風格,你或許一直在使用。

RESTful API 示例

REST是什麼?

如果有人這麼問你,你可以非常言簡意賅的告訴他:「REST是一個風格!」,用英文說就是 Style,那他是什麼風格呢?它是萬維網軟體架構風格

風格這個詞是非常關鍵的,因為它告訴我們,REST 不是協議,也不是什麼硬性的規範,僅僅就是一種架構風格而已。是一組架構約束條件和設計指導原則,一種基於HTTP、URI、XML 等現有協議與標準的開發方式。

為何叫REST?

REST並不是REST這個單詞休息的意思,而是 Representational State Transfer 的縮寫,表示表述性狀態轉移,這個說明比較晦澀抽象,難以理解。接下來拆開解釋。

  • Representational:在整個詞語中表示「數據的表現形式」,如(JSON、XML……),REST其實對數據的傳輸是不做任何限制的,儘管它不做任何限制,但我們在寫REST服務時的最佳實踐還是用JSON比較多。
  • State:當前狀態或者數據。什麼意思呢?比如說我們寫了一個用戶介面,一個用戶列表或單個用戶的數據,比如說姓名性別這些都是 State 都是數據,在 REST 這個片語里為什麼要用 State 來代表這些數據呢?因為如果我們對數據進行增刪改查那麼數據就變了,在變化的每一個階段它都是一種狀態,從狀態1變到狀態2等等,用狀態來描述數據更好的顯示了數據是會變化的是會被我我們所修改的。
  • Transfer:數據傳輸。在 REST 這個片語里它代表的是數據在互聯網上進行傳輸,比如從服務端傳輸到客戶端。

其實 REST 的字面意思是很難表達它的精髓的,接下來我們通過 REST 的 6 個限制來詳細了解它。這6個限制是REST的精髓,是它的重中之重,在面試中會經常考到。

REST的六個限制

REST給出了6種約束條件,通訊兩端在遵循這些約束後,就能提高工作效率,改善系統的可伸縮性、可靠性和交互的可見性,還能促進服務解耦。

客戶端-伺服器(Client-Server)

這個限制其實已經非常常見了,現在幾乎沒有什麼不是CS架構的,所以它也是沒有任何爭議的,值得一提的是這個限制的本質其實是一種軟體架構思想,叫做分離關注點,所謂關注點分離,用大白話說其實就是各掃門前雪,自己管好自己的事。這裡是指服務端專註數據存儲,提升了簡單性;前端專註於用戶介面,提升了可移植性

無狀態(Sateless)

所謂無狀態就是所有用戶會話資訊都保存在客戶端,意思就是所有的會話資訊服務端都不管,不要妄想讓服務端存著你的用戶資訊、用戶會話資訊、當前所處的狀態,服務端都不知道,因為服務端不管事了,所以每次請求必須包括所有資訊,不能依賴上下文資訊。

無狀態有什麼好處?好處就是服務端不用保存會話資訊,提升了簡單些、可靠性、可見性。

  • 簡單性。服務端少了很多程式碼自然就簡單了。
  • 可靠性。可靠性是指一個軟體的穩定程度,以及它從依次故障中恢復正常的能力。為什麼說它提升了可靠性呢?因為如果服務端要管用戶的會話資訊的話,一旦服務端出錯出現故障用戶會話資訊就會完全丟失,想要恢復起來機會是不可能的,所以說它的可靠性就會很差,但如果服務端不管你用戶會話資訊的話,那麼從故障中恢復起來就回非常的容易。
  • 可見性。是指在軟體工程中這些模組、介面之間的透明程度。為什麼說提升了可見性了呢?因為每次請求都必須包括所有資訊,所以說介面之間就更加透明了。

快取(Cache)

這個很好理解。是指所有服務端響應都要被標為可快取或不可快取,響應的資源可以被標記為可快取或禁止快取,如果可以快取,那麼客戶端可以減少與伺服器通訊的次數,降低延遲、提高效率。

統一介面(Uniform Interface)

這個限制是所有限制中最重要的一個,別的限制如果不是在 REST 裡面也可以遵循,比如CS架構,現在生活中幾乎都是CS架構 了,也不一定是REST風格,比如快取,別的風格也可以用到快取。但是只有統一介面凸出了REST的特點,區別於其他架構風格的核心特徵。(後面詳細講解)

統一介面是什麼意思呢,我們分開來看:

  • 統一。所謂統一指的是介面設計儘可能通用統一,遵循同一個規範,提升了簡單性、可見性。
  • 介面。介面與實現解耦,使前後端可以獨立開發迭代。

分層系統(Layers)

這個限制的意思是,軟體架構是分很多層的,而且每一層只知道相鄰額有一層,後面隱藏的就不知道了,比如客戶端不知道自己是在和代理還是在和真實的伺服器通訊,這裡的代理就是軟體分層中的一層,其它層比如:安全層、負載均衡層、快取層等。

按需程式碼(Code-On-Demand 可選)

這是一條可選的限制,也不是很重要。所謂按需程式碼是指客戶端可以下載運行服務端傳來的程式碼(比如JS),按需程式碼的好處是通過減少一些功能,簡化了客戶端。

統一介面的限制詳細

統一介面的限制的風格到底長什麼樣?下面說一下這個限制的子限制,介面定義包括4個部分。

  • 資源的標識。資源是任何可以命名的事物,比如用戶、評論等。REST整個都是圍繞資源展開的,不像其它一些風格可能是以動詞形式,REST裡面的資源都是一些名詞,不僅如此,每個資源都可以被URI唯一的標識。
  • 通過表述對資源執行操作。表述就是 Representational ,比如JSON、XML等。反過來理解,客戶端不能直接操作(比如SQL)服務端資源,客戶端只能通過表述(比如JSON)來操作資源,我覺得這個很好理解。
  • 自描述的消息。每個請求或響應必須提供足夠的資訊讓接受者理解,這些消息是指比如媒體類型、HTTP方法、是否快取
  • 超媒體作為應用狀態引擎。超媒體:帶文字的鏈接,應用狀態:一個網頁;引擎:驅動、跳轉,其實意思就是點擊鏈接跳轉到另一個網頁或者另一個JSON。

RESTful API 設計最佳實踐

請求設計規範

  • URI 使用名詞,盡量用複數,如/users
  • URI 使用嵌套標識關聯關係,如 /users/12/repos/5
  • 使用正確的HTTP方法,如GET/POST/PUT/DELETE
  • 不符合 CRUD 的情況:POST/action/子資源

響應設計規範

  • 查詢。意思是每一個響應都是可以被查詢的、都是可以被過濾的,我們給介面加上一些限制條件就只能返回符合這些條件的結果。
  • 分頁。本質上也是一種查詢,如果列表資訊非常長的話應該加上分頁資訊
  • 欄位過濾。只返回你指定的欄位
  • 狀態碼。選擇正確的狀態作為返回狀態
  • 錯誤處理。如果你的請求是錯的,那麼應用盡量把錯誤資訊給返回,並按照一個規範通用的格式

安全

  • HTTPS
  • 鑒權
  • 限流

開發者友好

  • 文檔
  • 超媒體

RESTful API 示例

下面是我是真實API截圖,用Swagger管理,基本遵循RESTful API架構風格

RESTful API 示例

路徑

HTTP動詞

  • GET(SELECT):從伺服器取出資源(一項或多項)。
  • POST(CREATE):在伺服器新建一個資源。
  • PUT(UPDATE):在伺服器更新資源(客戶端提供改變後的完整資源)。
  • PATCH(UPDATE):在伺服器更新資源(客戶端提供改變的屬性)。
  • DELETE(DELETE):從伺服器刪除資源。
  • HEAD:獲取資源的元數據。
  • OPTIONS:獲取資訊,關於資源的哪些屬性是客戶端可以改變的。

下面是一些例子

  • GET /zoos:列出所有動物園
  • POST /zoos:新建一個動物園
  • GET /zoos/ID:獲取某個指定動物園的資訊
  • PUT /zoos/ID:更新某個指定動物園的資訊(提供該動物園的全部資訊)
  • PATCH /zoos/ID:更新某個指定動物園的資訊(提供該動物園的部分資訊)
  • DELETE /zoos/ID:刪除某個動物園
  • GET /zoos/ID/animals:列出某個指定動物園的所有動物
  • DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物

狀態碼,伺服器向用戶返回的狀態碼和提示資訊,常見的有以下一些(方括弧中是該狀態碼對應的HTTP動詞)。

  • 200 OK – [GET]:伺服器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。
  • 201 CREATED – [POST/PUT/PATCH]:用戶新建或修改數據成功。
  • 202 Accepted – [*]:表示一個請求已經進入後台排隊(非同步任務)
  • 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 – [*]:伺服器發生錯誤,用戶將無法判斷發出的請求是否成功。

狀態碼的完全列表參見這裡

傳統介面寫法與Restful API 區別

這裡再區分以下傳統介面寫法與Restful API 的區別

一個文件操作介面,傳統模式:

  • api/getfile.php – 獲取文件資訊,下載文件
  • api/uploadfile.php – 上傳創建文件
  • api/deletefile.php – 刪除文件

RESTfu,api/file 只需要這一個介面:

  • GET 方式請求 api/file – 獲取文件資訊,下載文件
  • POST 方式請求 api/file – 上傳創建文件
  • DELETE 方式請求 api/file – 刪除某個文件

常見筆試題:什麼是 RESTful API,如何設計RESTful API?

答案: RESTful API。為了使得介面安全、易用、可維護以及可擴展,一般設計 RESTful API需要考慮以下幾個方面:

  1. 通訊用HTPS安全協議。
  2. 在URL中加入版本號,例如」vl/animals」
  3. URL中的路徑(endpoint)不能有動詞,只能用名詞。
  4. 用HTTP方法對資源進行增刪改查的操作。
  5. 用HTTP狀態碼傳達執行結果和失敗原因。
  6. 為集合提供過濾、排序、分頁等功能。
  7. 用查詢字元串或HTTP首部進行內容協商,指定返回結果的數據格式。
  8. 及時更新文檔,每個介面都有對應的說明。

你的公司使用的是RESTful API嗎?如果不是可以考慮辭職了,太落伍了!RESTful API 現在也要讓位新寵 GraphQL 了,一種更高效、強大和靈活的數據提供方式。

GraphQL

全文完。

本文代表個人觀點,內容僅供參考。若有不恰當之處,望不吝賜教!

本文鏈接:https://zhangbing.site/2019/07/28/前端要知道的RESTful-API架構風格/