團隊RESTful 風格API規範
實際上就是用RESTful風格來包裝HTTP協議,並用json或xml格式實現資料互動。
RESTful風格: 網路資源實體化,CURD對資源進行操作。
好的規範評判標準:直觀、擴充套件、優雅
1.資料互動格式
推薦json, 緊湊、易於讀寫、佔用頻寬小、各種程式語言支援。以下均已json格式為例。
HTTP 請求頭:
## 客戶端接受資料型別,服務端根據Accept欄位調整返回訊息的資料格式
Accept:application/json; charset=UTF-8 # >>>推薦
# 或 :application/xml; charset=UTF-8 # xml
# 或 :application/json,application/xml; charset=UTF-8 # xml或者json
## 客戶端傳送資料型別
Content-Type:application/json; charset=UTF-8 # >>>推薦
# 或 :application/x-www-form-urlencoded; charset=UTF-8 # 不推薦
# 或 :multipart/form-data; charset=UTF-8 # >>>推薦用於上傳檔案
# 或 :application/xml; charset=UTF-8 # xml
HTTP 訊息頭:
## 服務端端返回訊息資料型別
Content-Type:application/json; charset=UTF-8 # >>>推薦
# 或 :application/xml; charset=UTF-8 # xml
2.授權認證
由於HTTP是無狀態協議,所以客戶端需要攜帶一串經過加密的不易重複的密碼串來追蹤使用者。web中的session機制,OAuth2.0中的tooken。 比如:md5 36^32=6.3+E49 100億使用者重複的概率是億億億億分之一
2.1 針對web客戶端設計
由於web應用開發已經有成熟的使用者追蹤解決方案,即Session-Cookie,API設計可以延用這一方案。當客戶端請求Session不存在或過期的時候,介面返回響應錯誤碼要求使用者登陸;客戶端登陸成功後把session ID和其他使用者資訊放在Cookie裡,客戶端再次請求時攜帶該資訊。
HTTP 訊息頭:
Cookie:sessionId=39rkgbkm2qqt0k9d9qmnr68difn9bs9q;userId=1;userRole=admin; # "sessionId"鍵名可以由服務端自定義
HTTP 請求頭:
Cookie:sessionId=39rkgbkm2qqt0k9d9qmnr68difn9bs9q;userId=1;userRole=admin; # "sessionId"鍵名可以由服務端自定義
2.2 針對純API客戶端設計
客戶端不是瀏覽器時或客戶端不支援Cookie時,另起一個頭欄位“User”,當然可以是其他欄位甚至可以是“Cookie”,純粹習慣問題。客戶端獲取數居前需要解析下這個請求頭欄位(瀏覽器會自動解析Cookie欄位)。
HTTP 訊息頭:
User:token=39rkgbkm2qqt0k9d9qmnr68difn9bs9q;userId=1;userRole=admin; # "token"鍵名可以由服務端自定義
HTTP 請求頭:
User:token=39rkgbkm2qqt0k9d9qmnr68difn9bs9q;userId=1;userRole=admin; # "token"鍵名可以由服務端自定義
2.3 通用型
如果以上2.1和2.2兩種情況都用“Cookie”頭欄位,省事了沒有這一步;2.2用“User”的話就需要做個判斷處理。
2.4 個人推薦
User:tooken=39rkgbkm2qqt0k9d9qmnr68difn9bs9q;userId=1;userRole=admin;
3.API命名
API指的是服務端的資源實體,它可以是一段文字、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。所以API名稱一定是名稱,通常以複數居多,對應資料庫中的一張表,比如“users、goods、orders”。“轉賬”就可以當作一種服務:
GET http://.../transfer?from=a&to=b&amount=100
。
遞進從屬關係表達,如:
http://.../orders/1/goods/1
,表示訂單ID為1的訂單下面商品ID為1的商品。
3.請求
一次請求就是對服務的資源的一次操作,操作即增、刪、改、查,對應HTTP四種請求方法:GET(查)、POST(增)、PUT(改)、DELETE(刪)。
另有PATCH(打補丁)方法,指區域性跟新,PUT指全量更新;但一般PUT當全量更新用,而PATCH方法不用。
還有OPTIONS方法,是對該介面引數和功能的說明,類似於命令列中的"--help",建議使用。
## 建議在訊息頭說明
Allow:GET, POST, PUT, DELETE, OPTIONS
3.1 CURD舉例
GET http://.../goods # 列表 ?page=1&page_size=10&order_by=price&desc=1&filters={"price":{"min":10,"max":20}}
GET http://.../goods/1 # 詳情
POST http://.../goods # 新增 -d '{"name":"番茄","price":"3.00"}'
POST http://.../goods # 批量新增 -d '[{"name":"番茄","price":"3.00"}, ...]'
PUT http://.../goods/1 # 更新 -d '{"name":"番茄","price":"3.50"}'
PUT http://.../goods # 批量更新 -d '[{"id":1,name":"番茄","price":"3.00"}, ...]'
DELETE http://.../goods/1 # 刪除
DELETE http://.../goods/1,2 # 批量刪除
3.2 輔助引數
某種特殊情況下,需要對介面行為作出調節,需要客戶端額外的傳參;為了防止衝突,這種引數通常以"_"開頭。比如深度連結喚起應用、分享連結
# 模擬請求方法
_method=GET/POST/PUT/DELETE
# 標記碼
_token=39rkgbkm2qqt0k9d9qmnr68difn9bs9q
# 防止跨域攻擊標記碼
_CSRF_token=39rkgbkm2qqt0k9d9qmnr68difn9bs9q
# 格式化輸出
_format=json
4.訊息體
標準的訊息體由三個部分組成:
{
"code":200, // 狀態碼,參考http狀態碼,建議二者保持一致, 見[6.錯誤碼]
"msg":"SUCCESS", // 簡短訊息,可供客戶端直接列印輸出
"data":{}, // 資料包
}
4.1 列表
GET http://.../goods
{
"code":200,
"msg":"SUCCESS",
"data":{
"list":[{...}, {...}],
"count":12,
"page":1,
"page_size":10
},
}
4.2 詳情
GET http://.../goods/1
{
"code":200,
"msg":"SUCCESS",
"data":{
"detail":{"name":"番茄","price":"3.50"},
"comments":[{"rank:5, "content":"五星好評"},{...}]
},
}
4.3 POST或PUT驗證失敗
POST http://.../goods -d '{"name":"番茄","price":"3.50"}'
{
"code":406,
"msg":"驗證失敗, 請檢查是否按要求提交資料",
"data":{
"raw":{"name":"番茄","price":"3.50元"}, // 建議返回客戶端
"errors":[{"price":["請輸入數字型別"]}]
},
}
5.檔案上傳與下載
上傳檔案 HTTP 請求頭:
Content-Type:multipart/form-data
下載檔案 HTTP 請求頭:
Content-Type:參見http://www.runoob.com/http/http-content-type.html
6.錯誤碼
200 OK # 成功處理
400 Bad Request # 客戶端請求有語法錯誤,例如Content-Type與請求體不符或請求體無法解析
401 Unauthorized # 請求未經授權,例如需要登陸
403 Forbidden # 禁止操作該資源,例如許可權不夠等
404 Not Found # 請求資源不存在
405 Method Not Allowed # 方法未允許
406 Not Acceptable # 不可接受,未通過驗證,不符合要求
408 Request Timeout # 請求超時
500 Internal Server Error # 伺服器發生不可預期的錯誤
503 Server Unavailable # 伺服器當前不可用,一段時間後可能恢復正常,例如併發問題