這篇文章,主要想總結本身在設計RESTful API的一系列經驗于思考。前端
有些規範可能與標準規範有所出入,可是全部的考量都是基於『減小重複工做,增長可讀性可維護性』而出發的。話說回來,我一直以爲 RESTful API 設計,確實沒有很明顯的公認規範(若是你是指發明者的那篇論文,估計沒多少人詳細閱讀過,並且其做者只是提出了一系列概念而已)。網上的教程,彷佛都是千篇一概的(我嚴重懷疑:都是 「借鑑or拷貝」 阮一峯老師的那幾篇文章),僵硬並且呆板,有點教條化(歷來沒有人懷疑它們嗎,反正我按照這些教條設計API,沒有感覺到多少樂趣)。數據庫
以上,並非所有否認,好東西要充分吸取,很差的東西,要融合本身的理解,加以改造。後端
說到這個,彷佛又要談及『RESTful 是對資源的抽象』、『結合了HTTP 的特色』云云。不過這些都是一些沒用的套話,沒啥養分價值,而我想從另外的角度談論這個。安全
既然是 API,通常都符合 API 的通常模式:bash
ResultType ApiName(ParamType )
1. 接口參數,即形參。能夠是 string,int,以及其餘任意能夠稱之爲參數的東西
2. 接口返回值。能夠是 string,int,以及其餘任意能夠稱之爲返回值的東西
3. 接口名(簽名)
複製代碼
咱們來看看 RESTful 是如何對應上這個模式的:網絡
HttpResponse URL(HttpRequest)
1. HttpRequest:包括請求頭,URL參數,請求body參數
2. HttpResponse: 包括響應頭,響應的body
複製代碼
這樣來看,RESTful API 無非是一種特殊的API 而已,通用的 API 設計法則,一樣適合 RESTful,只不過非變換形式而已。架構
那麼咱們大概有哪些比較通用的標準呢?大概有這些:ide
下面就來看看這些標準,是如何影響下文的內容的,:)。spa
URL 就是接口簽名,而簽名必須作到清晰,沒有歧義。設計
若是後端架構是服務化的,那麼有可能每一個服務會對外提供公共的 RESTful API,那麼有個統一的前綴格式,會比較好,好比:
/SERVICE_NAME/v1/users
or
/APP_NAME/v2/users
複製代碼
同一份資源,能夠有不一樣的路徑,去理解它。好比:
User -- 1:N --> Server-- 1:N --> Client ... 更加複雜的實體映射關係
1. /users/{user_id}/servers/{server_id}/clients
2. /clients
通常你們傾向於選項 1(可是實體關聯關係特複雜時,會縮短URL),
不過選項2 也是一個不錯的選擇,總而言之,口味問題吧。
複製代碼
接口數量越少越好,能合併的接口就儘可能合併。好比,這樣的狀況:
獲取用戶列表信息:GET /users
獲取單個用戶信息:GET /users/{id}
坦白說,獲取一個與獲取一批,彷佛並無什麼語義上的差異,
可是後端的同窗就不同了,他可能須要寫兩個 View Class。
因此只保留批量的接口,查詢一個時,用 URL 參數傳遞就好了。
複製代碼
這樣的狀況:
PUT /users/{id}
PUT /users
直接合併到一個接口裏面作就好了,PUT 一個 user與 PUT 一羣 user,有啥本質的不一樣嗎?
複製代碼
還有這樣極端的狀況:
DELETE /users/{id}
刪除一個user與刪除一批user,有啥不一樣?
若是要一次刪除100 個 user,難道讓前端同窗,調 100 次這個接口?
多一次調用,就多一次風險(如網絡問題),
這個時候就別守着 RESTful 那些個教條了,接口的可用性、效率性,更加劇要。
這個時候,不如設計成這樣(至於 DELETE 接口能不能傳Request body,這裏不討論):
POST /users_deletion
{
"user_ids": [1, 2, 3, 4, 5]
}
複製代碼
前面有說到,HttpResponse中,咱們能夠利用:
Response Headers
能夠作少許文章,如自定義一個Header
Status Code
按照基本規範來,該404的404,該200的200
Response body
基本都是圍繞這個作文章
複製代碼
Response body 既要能正常返回信息,出錯了也要告訴出錯緣由(錯誤碼),出錯詳情。因此咱們大概能夠設計成這樣:
{
是否成功
boolean "is_success":
錯誤碼是多少
number|null "err_code":
錯誤信息
string|null "err_msg":
錯誤詳情(可選)
string|null "err_detail":
出錯的時哪一個服務
string|null "provider":
正常返回時的數據
"response_data": {
}
}
複製代碼
這樣,前端調用 API ,就有章法可循了,不至於盲目。
沒有很明確的規範,可是儘可能跟隨數據庫的風格,即:下劃線風格。 這樣,在 序列化整個 Model 時,也許會很方便。
參考 GitHub 的風格。
這個無法系統化,能夠參考網絡上相關文章。