RESTful 規范指南:
1. HTTP 協議
API 與用戶的通信協議, 總是使用 HTTPS 協議
2. 域名:
3. 版本:
4. 路徑
視網絡上的一切都為資源, 均使用名詞表示(可使用復數)
5. method
6. 過濾:
通過在 URL 上傳參的形式傳遞搜索條件
7. 狀態碼:
- 常用狀態碼:
- 狀態碼和 code 結合使用
- 全部狀態碼:
8. 錯誤處理
狀態碼是 4xx 時, 應返回錯誤信息, error 當作 key
9. 返回結果
針對不同操作, 服務器向用戶返回的結果應該符合以下規范:
Restful API 的設計規范–進階篇 原文鏈接
本文總結了 RESTful API 設計相關的一些原則,只覆蓋了常見的場景。有些規則只是針對自己項目而言,並非其他做法都是錯誤的。
1. URI
URI 表示資源,資源一般對應服務器端領域模型中的實體類。 URI規范
- 不用大寫;
- 用中杠
-
而不用下杠_
; - 參數列表要encode;
- URI中的名詞表示資源集合,使用復數形式;
資源集合與單個資源 資源集合:
單個資源:
避免層級過深的URI /
在URI中表示層級,用於按實體關聯關系進行對象導航,一般跟進id導航; 過深的導航容易導致url膨脹,不易維護,如 GET /zoos/1/areas/3/animals/4
,盡量使用查詢參數代替路徑中的實體導航,如GET /animals?zoo=1&area=3
;
對Composite資源的訪問 服務器端的組合實體必須在uri中通過父實體的id導航訪問。
組合實體不是first-class的實體,它的生命周期完全依賴父實體,無法獨立存在,在實現上通常是對數據庫表中某些列的抽象,不直接對應表,也無id。一個常見的例子是 User — Address,Address是對User表中zipCode/country/city三個字段的簡單抽象,無法獨立於User存在。必須通過User索引到Address:
GET /user/1/addresses
2. Request
HTTP方法 通過標准HTTP方法對資源CRUD: GET: 查詢
POST: 創建單個資源。POST一般向“資源集合”型URI發起; ··· javaascipt
PUT:更新單個資源(全量),客戶端提供完整的更新后的資源。與之對應的是 PATCH,PATCH 負責部分更新,客戶端提供要更新的那些字段。PUT/PATCH一般向“單個資源”型uri發起
DELETE:刪除
HEAD / OPTION 用的不多,就不多解釋了。
安全性與冪等性 安全性:不會改變資源狀態,可以理解為只讀的; 冪等性:執行1次和執行N次,對資源狀態改變的效果是等價的。
安全性和冪等性均不保證反復請求能拿到相同的response。以 DELETE 為例,第一次DELETE返回200表示刪除成功,第二次返回404提示資源不存在,這是允許的。
復雜查詢 查詢可以捎帶以下參數:
Bookmarker 經常使用的、復雜的查詢標簽化,降低維護成本。 如:
快捷方式:
Format 只用以下常見的3種body format:
- Content-Type: application/json
- Content-Type: application/x-www-form-urlencoded (瀏覽器POST表單用的格式)
- Content-Type: multipart/form-data; boundary=—-RANDOM_jDMUxq4Ot5 (表單有文件上傳時的格式)
Content Negotiation 資源可以有多種表示方式,如json、xml、pdf、excel等等,客戶端可以指定自己期望的格式,通常有兩種方式:
- http header
Accept
:
q為各項格式的偏好程度
- url中加文件后綴:
/zoo/1.json
3. Response
不要包裝
response 的 body 直接就是數據,不要做多余的包裝。錯誤示例:
- 各HTTP方法成功處理后的數據格式:
- json格式的約定: 時間用長整形(毫秒數),客戶端自己按需解析(moment.js) 不傳
null
字段
分頁response
4. 錯誤處理
- 不要發生了錯誤但給2xx響應,客戶端可能會緩存成功的http請求;
- 正確設置http狀態碼,不要自定義;
- Response body 提供 1) 錯誤的代碼(日志/問題追查);2) 錯誤的描述文本(展示給用戶)。
對第三點的實現稍微多說一點: Java 服務器端一般用異常表示 RESTful API 的錯誤。API 可能拋出兩類異常:業務異常和非業務異常。業務異常由自己的業務代碼拋出,表示一個用例的前置條件不滿足、業務規則沖突等,比如參數校驗不通過、權限校驗失敗。非業務類異常表示不在預期內的問題,通常由類庫、框架拋出,或由於自己的代碼邏輯錯誤導致,比如數據庫連接失敗、空指針異常、除0錯誤等等。 業務類異常必須提供2種信息:
- 如果拋出該類異常,HTTP 響應狀態碼應該設成什么;
- 異常的文本描述;
在Controller層使用統一的異常攔截器:
- 設置 HTTP 響應狀態碼:對業務類異常,用它指定的 HTTP code;對非業務類異常,統一500;
- Response Body 的錯誤碼:異常類名
- Response Body 的錯誤描述:對業務類異常,用它指定的錯誤文本;對非業務類異常,線上可以統一文案如“服務器端錯誤,請稍后再試”,開發或測試環境中用異常的 stacktrace,服務器端提供該行為的開關。
5. 服務型資源
除了資源簡單的CRUD,服務器端經常還會提供其他服務,這些服務無法直接用上面提到的URI映射。如:
- 按關鍵字搜索;
- 計算地球上兩點間的距離;
- 批量向用戶推送消息;
可以把這些服務看成資源,計算的結果是資源的presentation,按服務屬性選擇合適的HTTP方法。 例如:
6. 異步任務
對耗時的異步任務,服務器端接受客戶端傳遞的參數后,應返回創建成功的任務資源,其中包含了任務的執行狀態。客戶端可以輪訓該任務獲得最新的執行進度。
如果任務的執行狀態包括較多信息,可以把“執行狀態”抽象成組合資源,客戶端查詢該狀態資源了解任務的執行情況。
7. API演進
版本 常見的三種方式:
- 在uri中放版本信息:
GET /v1/users/1
- Accept Header:
Accept: application/json+v1
- 自定義 Header:
X-Api-Version: 1
用第一種,雖然沒有那么優雅,但最明顯最方便。
URI失效 隨着系統發展,總有一些API失效或者遷移,對失效的API,返回404 not found 或 410 gone;對遷移的API,返回 301 重定向。