RESTful API淺談

https://www.cnblogs.com/imyalost/p/7923230.html


上半年時候,部門有組織的討論了一下實踐微服務的技術話題,主要內容是SOA服務和微服務各自的優勢和難點,其中有提到關於RESTful API設計方法。

正好最近在深入的學習HTTP協議,也看了一些有關RESTful API的資料,這篇博客,就將自己的一些理解整理記錄一下。

PS:本篇博客主要談一些概要的設計思想和方法,不談具體的實現細節,如有誤差歡迎指出,謝謝!

想進一步瞭解RESTful API,建議學習下面列出的一些詞條:

HTTP協議、分佈式系統架構原理(CAP)、操作系統原理。。。

參考資料:

跟着Github學習RESTful HTTP API設計

一種RESTful API接口的約定

RESTful API設計最佳實踐

知乎:如何用通俗易懂的語言解釋RESTful API?

 

一、REST的由來

全稱:REST,全稱是Resource Representational State Transfer,即:資源在網絡中以某種形式進行狀態轉移。————所謂狀態的轉移,可參考《HTTP權威指南》一書中對協議的詳細解釋,此處不過多贅述!

出現:REST最早是由Roy Fielding博士發表的論文中提到的,他也曾參與設計了HTTP協議。論文地址:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

定義:簡單來說REST是一種系統架構設計風格(而非標準),一種分佈式系統的應用層解決方案。

背景:早期的網頁端是前後臺一起的,比如PHP、JSP等。而隨着近幾年移動端的快速發展和分佈式架構的應用,各種Client層出不窮,這個時候就需要有個統一的機制,來爲前後端通信提供服務。

     而RESTful API就是目前比較成熟的的一套應用程序API設計理論。

目的:Client和Server端進一步解耦。

應用:最爲經典的莫過於github API。

 

二、RESTful的特徵和優點

1、客戶端-服務器(Client-Server):提供服務的服務器和使用服務的客戶端分離解耦;

   優點:提高客戶端的便捷性(操作簡單)

        簡化服務器提高可伸縮性(高性能、低成本)

        允許客戶端服務端分組優化,彼此不受影響

2、無狀態(Stateless):來自客戶的每一個請求必須包含服務器處理該請求所需的所有信息(請求信息唯一性);

   優點:提高可見性(可以單獨考慮每個請求)

        提高可靠性(更容易故障恢復)

        提高了可擴展性(降低了服務器資源使用)

3、可緩存(Cachable):服務器必須讓客戶端知道請求是否可以被緩存?如果可以,客戶端可以重用之前的請求信息發送請求;

   優點:減少交互連接數

        減少連接過程的網絡時延

4、分層系統(Layered System):允許服務器和客戶端之間的中間層(代理,網關等)代替服務器對客戶端的請求進行迴應,而客戶端不需要關心與它交互的組件之外的事情;

   優點:提高了系統的可擴展性

        簡化了系統的複雜性

5、統一接口(Uniform Interface):客戶和服務器之間通信的方法必須是統一化的。(例如:GET,POST,PUT.DELETE)

   優點:提高交互的可見性

        鼓勵單獨優化改善組件

6、支持按需代碼(Code-On-Demand,可選):服務器可以提供一些代碼或者腳本並在客戶的運行環境中執行。

   優點:提高可擴展性

 

三、概要設計方法

1、協議

API與Client的通信協議,總是使用HTTPS協議。

PS:使用HTTPS協議和RESTful API本身沒有多大關係,但是對於增加網站的安全是非常重要的,特別是如果提供的是公開的API,那麼HTTPS久更顯得重要了。

2、域名

應該儘量將API部署在專用的域名下面,比如:

 https://api.github.com 

如果API變化較大,可以把API設計爲子域名,比如:

 https://example.com/api/v1 

3、版本(Versioning)

一般而言應該將API放入URL中,比如:

 https://example.com/api/v1 

還可以將版本號放入HTTP信息頭中,但這樣不如放入URL方便和直觀。

4、路徑(Endpoint)

在協議中,每個網址代表一種資源的存放地址,所以網址終不能有動詞,只能有名詞,而且名詞一般都應該與數據庫的表字段對應,且API中的名詞應該使用複數。例如:

/users/:username/repos/users/:org/repos/repos/:owner/:repo/repos/:owner/:repo/tags/repos/:owner/:repo/branches/:branch

PS:根據RFC3986定義,URL是大小寫敏感的,所以應該儘量使用小寫字母來命名!

5、方法(Method)

有了資源的URL設計,所有針對資源的操作都是使用HTTP方法指定的,常見的方法有(括號中爲對應的SQL命令):

Verd描述
HEAD(SELECT)只獲取某個資源的頭部信息
GET(SELECT)獲取資源
POST(CREATE)創建資源
PATCH(UPDATE)更新資源的部分屬性(很少用,一般用POST代替)
PUT(UPDATE)更新資源,客戶端需要提供新建資源的所有屬性
DELETE(DELETE)刪除資源

比如:

GET /user:列出所有的用戶POST /user:新建一個用戶PATCH /user/ID:更新某個指定用戶的信息DELETE /user/ID:刪除所有用戶

6、數據過濾(Filtering)

如果數據量太大,服務器不可能將所有數據返回給用戶。API應該提供參數(比如Query),過濾返回結果。比如:

?limit=10:指定返回記錄的數量?offset=10:指定返回記錄的開始位置?page=2&per_page=100:指定第幾頁,以及每頁的記錄數?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序?state=close:指定篩選條件

7、狀態碼

在HTTP報文構成中,有個字段很重要:status code。它說明請求的大致情況,是否正常處理、出現了什麼錯誤等。狀態碼都是三位數,大概分爲了一下幾個區間:

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

關於狀態碼,具體的介紹可以去我之前的博客HTTP狀態碼或者參考其他資料,這裏不過多贅述。

8、錯誤處理

如果出錯的話,在response body中應通過message字段,以鍵值對的格式,給出明確的錯誤信息。

最基本的思路應該是:儘可能提供準確的錯誤信息,比如數據格式不正確、缺少某個字段......而不是直接說“請求錯誤”之類的信息。

9、Hypermedia API

Restful API的設計最好做到Hypermedia:即在返回結果中提供相關資源的鏈接,連向其他API方法,使用戶不需要查文檔也知道下一步做什麼。

這樣做的好處是,用戶可以根據返回結果就能得到後續操作需要訪問的地址。

10、身份驗證

一般來說,讓任何人隨意訪問公開的 API 是不好的做法,驗證和授權是兩件事情:

驗證(Authentication):確定用戶是其申明的身份,比如提供賬戶的密碼。不然的話,任何人僞造成其他身份(比如其他用戶或者管理員)是非常危險的;

授權(Authorization):保證用戶有對請求資源特定操作的權限。比如用戶的私人信息只能自己能訪問,其他人無法看到;有些特殊的操作只能管理員可以操作,其他用戶有隻讀的權限等。

如果沒有通過驗證,需要返回401 Unauthorized狀態碼,並在 body 中說明具體的錯誤信息;而沒有被授權訪問的資源操作,需要返回403 Forbidden狀態碼,還有詳細的錯誤信息。

PS:Github API 對某些用戶未被授權訪問的資源操作返回404 Not Found,目的是爲了防止私有資源的泄露(比如***可以自動化試探用戶的私有資源,返回 403 的話,就等於告訴***用戶有這些私有的資源)。

11、編寫文檔

API最終是給人使用的,無論是對內還是對外,即使遵循上面提到的所有規則,API設計的很優雅,但有時候用戶還是不知道該如何使用這些提供的API。

因此,編寫清晰可讀的文檔是很必要的事情。

而且編寫文檔也可以作爲產出物的一部分,以及用來做記錄,以方便查詢參考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章