作者:阮一峰
網絡應用程式,分為前端和後端兩個部分。目前的發展趨勢,就是前端裝置層出不窮(手機、平闆、桌面電腦、其他專用裝置……)。
是以,必須有一種統一的機制,友善不同的前端裝置與後端進行通信。這導緻api構架的流行,甚至出現“api first”的設計思想。restful api是目前比較成熟的一套網際網路應用程式的api設計理論。我以前寫過一篇《了解restful架構》,探讨如何了解這個概念。
今天,我将介紹restful api的設計細節,探讨如何設計一套合理、好用的api。我的主要參考資料是這篇《principles of good restful api design》。

api與使用者的通信協定,總是使用https協定。
應該盡量将api部署在專用域名之下。
</blockquote>
如果确定api很簡單,不會有進一步擴充,可以考慮放在主域名下。
應該将api的版本号放入url。
另一種做法是,将版本号放在http頭資訊中,但不如放入url友善和直覺。
路徑又稱”終點”(endpoint),表示api的具體網址。
在restful架構中,每個網址代表一種資源(resource),是以網址中不能有動詞,隻能有名詞,而且所用的名詞往往與資料庫的表格名對應。一般來說,資料庫中的表都是同種記錄的”集合”(collection),是以api中的名詞也應該使用複數。
舉例來說,有一個api提供動物園(zoo)的資訊,還包括各種動物和雇員的資訊,則它的路徑應該設計成下面這樣。
https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employees
對于資源的具體操作類型,由http動詞表示。
常用的http動詞有下面五個(括号裡是對應的sql指令)。
get(select):從伺服器取出資源(一項或多項)。 post(create):在伺服器建立一個資源。 put(update):在伺服器更新資源(用戶端提供改變後的完整資源)。 patch(update):在伺服器更新資源(用戶端提供改變的屬性)。 delete(delete):從伺服器删除資源。
還有兩個不常用的http動詞。
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:删除某個指定動物園的指定動物
如果記錄數量很多,伺服器不可能都将它們傳回給使用者。api應該提供參數,過濾傳回結果。
下面是一些常見的參數。
?limit=10:指定傳回記錄的數量 ?offset=10:指定傳回記錄的開始位置。 ?sortby=name&order=asc:指定傳回結果按照哪個屬性排序,以及排序順序。 ?animal_type_id=1:指定篩選條件
參數的設計允許存在備援,即允許api路徑和url參數偶爾有重複。比如,get /zoo/id/animals 與 get /animals?zoo_id=id 的含義是相同的。
伺服器向使用者傳回的狀态碼和提示資訊,常見的有以下一些(方括号中是該狀态碼對應的http動詞)。
200 ok – [get]:伺服器成功傳回使用者請求的資料,該操作是幂等的(idempotent)。 201 created – [post/put/patch]:使用者建立或修改資料成功。 204 no content – [delete]:使用者删除資料成功。 400 invalid request – [post/put/patch]:使用者發出的請求有錯誤,伺服器沒有進行建立或修改資料的操作,該操作是幂等的。。 404 not found – [*]:使用者發出的請求針對的是不存在的記錄,伺服器沒有進行操作,該操作是幂等的。 500 internal server error – [*]:伺服器發生錯誤,使用者将無法判斷發出的請求是否成功。
狀态碼的完全清單參見這裡。
如果狀态碼是4xx,就應該向使用者傳回出錯資訊。一般來說,傳回的資訊中将error作為鍵名,出錯資訊作為鍵值即可。
針對不同操作,伺服器向使用者傳回的結果應該符合以下規範。
get /collection:傳回資源對象的清單(數組) get /collection/resource:傳回單個資源對象 post /collection:傳回新生成的資源對象 put /collection/resource:傳回完整的資源對象 patch /collection/resource:傳回完整的資源對象 delete /collection/resource:傳回一個空文檔
restful api最好做到hypermedia,即傳回結果中提供連結,連向其他api方法,使得使用者不查文檔,也知道下一步應該做什麼。
比如,當使用者向api.example.com的根目錄送出請求,會得到這樣一個文檔。
上面代碼表示,文檔中有一個link屬性,使用者讀取這個屬性就知道下一步該調用什麼api了。rel表示這個api與目前網址的關系(collection關系,并給出該collection的網址),href表示api的路徑,title表示api的标題,type表示傳回類型。
hypermedia api的設計被稱為hateoas。github的api就是這種設計,通路api.github.com會得到一個所有可用api的網址清單。
從上面可以看到,如果想擷取目前使用者的資訊,應該去通路api.github.com/user,然後就得到了下面結果。
上面代碼表示,伺服器給出了提示資訊,以及文檔的網址。
(1)api的身份認證應該使用oauth 2.0架構。
(2)伺服器傳回的資料格式,應該盡量使用json,避免使用xml。
(完)
源自阮一峰個人部落格