RESTful API 設計指南——最佳實踐
RESTful API 設計指南——最佳實踐
Facebook、谷歌、Github、Netflix 和幾個其他的科技巨頭已經允許開發者和其產品通過 API 呼叫他們的資料,併為他們提供平臺。即使你不是寫 API 的專業人士,擁有精美的 API 也對你的應用程式有好處。
關於設計 API 的最好方法,網路上有較長一段時間的爭論,但官方也沒有對此給出解釋。
API 是一個介面,通過它許多開發者可與資料互動。 設計優良的 API 使用起來很方便,並給開發者的工作帶來便利。 API 是開發者的 GUI,如果它設計不合理,開發者會將它替換。所以,開發者的經驗是衡量 API 質量的最重要的指標。
--API就像一個在舞臺上表演的藝術家,其使用者就是其觀眾
1) 術語
以下是與 REST API 相關的重要術語:
-
資源(Resource) 是一個物件或對某物的表示。它有一些相關聯的資料,並有一組方法進行操作。 例如:動物,學校和員工是資源。這些資源都有著刪除,新增,更新操作。
-
集合(Collection)是一系列資源,例如:公司集合是很多公司的集合。
-
URL(統一資源定位符)是一種路徑,可以通過它定位資源並且也可以對它執行一些動作。
2) API 端點(路徑)
為了更好理解,我們給公司寫 API,這些公司都有一些員工。/getAllEmployees 是對員工列表進行迴應的 API。公司其他 API 大致如下:
-
/addNewEmployee
-
/updateEmployee
-
/deleteEmployee
-
/deleteAllEmployees
-
/promoteEmployee
-
/promoteAllEmployees
並且將有大量的和這些操作不同的 API 端點,它們包含大量冗餘的行為。因此,當 API 數量增加時,這些 API 端點將很難維護。
哪裡不對?
每個 URL 代表一種資源(Resource),所以 URL 中只能有名詞,不能有動詞。 API 路徑 /addNewEmployee 包含了操作 addNew 和資源名稱 Employee。
那麼怎樣算是正確的方式?
/companies 是一個很好的不包含操作的例子。但是問題來了,我們該怎樣告訴伺服器我們要進行的操作呢?新增,刪除,還是更新?
這時 HTTP 方法(GET,POST,DELETE,PUT)(也稱為動詞)就可以起到作用了。
資源在 API 端點中應該總是複數,如果我們想訪問資源的一個例項,我們可以傳遞 URL 中的 id。
-
方法 GET 路徑 /companies 是獲取所有公司的列表。
-
方法 GET 路徑 /companies/34 是獲取公司34的詳細資訊。
-
方法 DELETE 路徑 /companies/34 是刪除公司34.
在其他的一些使用案例中,如果我們有一些資源在某個資源之下,例如,一個公司的員工,那麼在這樣的例子中 API 的 endpoint(端點) 就應該是這樣的:
-
GET /companies/3/employees 可以取得編號為3的公司的員工列表
-
GET /companies/3/employees/45 可以取得編號為3的公司的45號員工的細節資訊
-
DELETE /companies/3/employees/45 可以刪除編號為3的公司的45號員工
-
POST /companies 可以建立一個新公司並返回新建立公司的細節資訊
現在這樣,API 是不是更嚴謹和一致了呢?
結論:路徑應該包含資源的複數形式,HTTP 方法應該定義成各種行為在資源上執行。
3) HTTP 方法 (動詞)
HTTP 定義了幾組方法,這些方法給出了對資源要執行的操作型別。
--URL 是一個句子,其中資源是名詞,HTTP 方法是動詞。
主要的HTTP方法如下:
-
GET 方法從資源請求資料,不產生多餘結果。
例如: /companies/3/employees 會返回公司3的所有僱員列表。 -
POST 方法請求伺服器在資料庫中建立資源,這主要用於提交 Web 表單時。
例如: /companies/3/employees 建立一個公司3的新僱員。
POST 是非冪等的,這意味著多個請求將會有不同的效果。 -
PUT 方法請求伺服器更新資源或建立資源(如果不存在的話)。
例如: /companies/3/employees/john 將請求伺服器在公司3的僱員集合中更新或在不存在的情況下建立關於 john 的資源。
PUT 是冪等的,這意味著多次請求具有相同的效果。 -
DELETE 方法將請求的資源或例項從資料庫中刪除。
例如: /companies/3/employees/john/ 將請求伺服器從公司3的僱員集中刪除 john 資源。
HTTP 中還有很多其他方法,我們將在另一篇文章中討論。
4) HTTP 響應狀態碼
當客戶端通過 API 向伺服器發起請求時,無論請求是失敗的、通過的還是錯誤的,客戶端應該獲得反饋。HTTP 狀態碼是一堆標準化的數值碼,在不同的情況下具有不同的解釋。伺服器應始終返回正確的狀態碼。
以下是 HTTP 狀態碼的主要分類:
2xx (成功類別)
這些狀態程式碼表示請求的操作已被伺服器接收到併成功處理。
-
200 Ok:標準的 HTTP 響應,表示 GET、PUT 或 POST 的處理成功。
-
201 Created:在建立新例項時,應返回此狀態程式碼。例如,使用 POST 方法建立一個新的例項,應該始終返回 201 狀態碼。
-
204 內容不存在:表示請求已被成功處理,但並未返回任何內容。
DELETE算是其中一個很好的例子。
API DELETE /companies/43/employees/2 將刪除員工 2,作為響應,我們不需要在該 API 的響應正文中的任何資料,因為我們明確地要求系統將其刪除。如果有任何錯誤發生,例如,如果員工 2 在資料庫中不存在,那麼響應碼將不是 2xx 對應的成功類別,而是 4xx 客戶端錯誤類別。
3xx (重定向類別)
-
304 未修改:表示客戶端的響應已經在其快取中。 因此,不需要再次傳送相同的資料。
4xx (客戶端錯誤類別)
這些狀態程式碼表示客戶端發起了錯誤的請求。
-
400 錯誤請求:表示客戶端的請求沒有被處理,因為伺服器不能理解客戶端請求的是什麼。
-
401 未授權:表示客戶端不被允許訪問該資源,需要使用指定憑證重新請求。
-
403 禁止訪問:表示請求是有效的並且客戶端已通過身份驗證,但客戶端不被允許以任何理由訪問對應頁面或資源。 例如有時授權的客戶端不被允許訪問伺服器上的目錄。
-
404 未找到:表示所請求的資源現在不可用。
-
410 資源不可用:表示所請求的資源後續不再可用,該資源已被移動。
5xx(伺服器錯誤類別)
-
500是伺服器內部錯誤,表示請求已經被接收到了,但伺服器被要求處理某些未預設的請求而完全混亂。
-
503服務不可用表示伺服器已關閉或無法接收和處理請求。大多數情況是伺服器正在進行維護。
5) 欄位套管約定
您可以遵循任何套管約定,但要確保其在應用程式中一致。如果請求主體或響應型別是JSON,那麼請按照camelCase(駝峰命名法)來保持一致。
6) 搜尋、排序、過濾和分頁
這些行為都只是針對一個數據集進行的查詢。由於還沒有一套新的 API 來處理這些行為。因此,我們需要向 GET 方法的 API 附加查詢引數。
我們來理解幾個例子看它們是如何實現這些行為的。
-
排序(sorting),客戶端想要獲得排序後的公司列表,GET /companies 端點應當接受多個查詢排序引數。
例如,GET /companies?sort=rank_asc 將根據等級以升序的方式對公司進行排序。 -
過濾(Filtering),用來過濾資料集,我們可以通過查詢引數傳遞不同的選項。
例如,GET /companies?category=banking&location=india 將根據公司類別為銀行以及所處位置為印度來過濾公司的列表資料。 -
搜尋(Searching),當需要在公司列表中搜索公司名稱時,API 端點應當是 GET /companies?search=Digital Mckinsey。
-
分頁(Pagination),當資料集太大時,我們將資料集分成更小的塊,這樣有助於提高效能,並且更易於處理響應。 例如,GET /companies?page=23 表示獲取第 23 頁的公司列表。
如果在 GET 方法中附加了很多查詢引數,會造成 URI 太長,伺服器可能會響應 414 的 HTTP 狀態,表示這個 URI 太長,在這種情況下,我們也可以將引數傳遞給 POST 方法的請求體中。
7) 版本控制
當你的 API 被開始被廣泛使用後,突然升級API會打破現有的產品、服務。
http://api.yourservice.com/v1/companies/34/employees 是一個很好的例子,它的路徑中有API的版本號。如果有任何重大的中斷更新,我們可以將新的API集命名為v2或v1.x.x
這些指南是根據我的開發經驗編寫的。我很想知道你對上述幾點的看法。