實際上就是用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 # 服務器當前不可用,一段時間後可能恢復正常,例如併發問題