1. 程式人生 > >RESTful API 設計指南——最佳實踐

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方法如下: 

  1. GET 方法從資源請求資料,不產生多餘結果。
    例如: /companies/3/employees 會返回公司3的所有僱員列表。

  2. POST 方法請求伺服器在資料庫中建立資源,這主要用於提交 Web 表單時。
    例如: /companies/3/employees 建立一個公司3的新僱員。 
    POST 是非冪等的,這意味著多個請求將會有不同的效果。

  3. PUT 方法請求伺服器更新資源或建立資源(如果不存在的話)。
    例如: /companies/3/employees/john 將請求伺服器在公司3的僱員集合中更新或在不存在的情況下建立關於 john 的資源。
    PUT 是冪等的,這意味著多次請求具有相同的效果。 

  4. 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

這些指南是根據我的開發經驗編寫的。我很想知道你對上述幾點的看法。