Restful API 設計參考原則
在項目中,需要為後臺服務撰寫API。剛開始接觸的時候,並沒有考慮太多,就想提供URL,服務端通過該URL進行查詢、創建、更新等操作即可。但再對相關規範進行了解後,才發現,API的設計並沒有那麽簡單,遠遠不是URL的問題,而是一個通信協議的整體架構
1. 使用GET、POST、PUT、DELETE這幾種請求模式
請求模式也可以說是動作、數據傳輸方式,通常我們在web中的form有GET、POST兩種,而在HTTP中,存在下發這幾種。
GET (選擇):從服務器上獲取一個具體的資源或者一個資源列表。
POST (創建): 在服務器上創建一個新的資源。
PUT(更新):以整體的方式更新服務器上的一個資源。
DELETE(刪除):刪除服務器上的一個資源。
2.使用名詞而不是動詞
Resource |
GET 讀 |
POST 創建 |
PUT 修改 |
DELETE |
/cars | 返回 cars集合 | 創建新的資源 | 批量更新cars | 刪除所有cars |
/cars/711 | 返回特定的car | 該方法不允許(405) | 更新一個指定的資源 | 擅長指定資源 |
不要使用:
/getAllCars
/createNewCar
/deleteAllRedCars
3.Get方法和查詢參數不應該涉及狀態改變
使用PUT, POST 和DELETE 方法 而不是 GET 方法來改變狀態,不要使用GET 進行狀態改變:
GET /users/711?activate
GET /users/711/activate
4.使用復數名詞
不要混淆名詞單數和復數,為了保持簡單,只對所有資源使用復數。
/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而部署 /setting
5. 使用子資源表達關系
如果一個資源與另外一個資源有關系,使用子資源:
GET /cars/711/drivers/ 返回 car 711的所有司機
6.為集合提供過濾 排序 選擇和分頁等功能
比如在數據過多, 需要對數據進行分頁請求的時候, 我們應該統一 API 請求參數. 常見的有這些.
limit=10
指定返回記錄的數量offset=10
指定返回記錄的開始位置。page=2&per_page=100
指定第幾頁,以及每頁的記錄數。sortby=name&order=asc
指定返回結果按照哪個屬性排序,以及排序順序。animal_type_id=1
指定篩選條件
Filtering過濾:
使用唯一的查詢參數進行過濾:
GET /cars?color=red 返回紅色的cars
GET /cars?seats<=2 返回小於兩座位的cars集合
Sorting排序:
允許針對多個字段排序
GET /cars?sort=-manufactorer,+model
這是返回根據生產者降序和模型升序排列的car集合
Field selection
移動端能夠顯示其中一些字段,它們其實不需要一個資源的所有字段,給API消費者一個選擇字段的能力,這會降低網絡流量,提高API可用性。
GET /cars?fields=manufacturer,model,id,color
Paging分頁
使用 limit 和offset.實現分頁,缺省limit=20 和offset=0;
GET /cars?offset=10&limit=5
為了將總數發給客戶端,使用訂制的HTTP頭: X-Total-Count.
鏈接到下一頁或上一頁可以在HTTP頭的link規定,遵循Link規定:
Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",
7.版本化你的API
API的開發直接關系了APP是否可以正常使用,如果原本運行正常的API,突然改動,那麽之前使用這個API的APP可能無法正常運行。APP是不可能強迫用戶主動升級的,因此,通過API版本來解決這個問題。也就是說,API的多個版本是同時運行的,而且都要保證可以正常使用。
按照RESTful的規範,不同的版本也應該用相同的API URL,通過header信息來判斷版本,再調用不同版本的程序進行處理。但是這明顯會給開發帶來巨大的成本。使得API版本變得強制性,不要發布無版本的API,使用簡單數字,避免小數點如2.5.
解決辦法有以下幾種:
1.新版本兼容舊版本,所有舊版本的動作、字段、操作,都在新版本中可以被實現,但明顯這樣的維護成本很大;
2.不同的版本,用不同的URL來提供服務,在URL中通過v1、v2來區分版本號,比如v2.api.xxx.com/user的方式,或者http://api.domain.com/v2 或者http://www.domain.com/api/v2 。
3.每個接口有各自的版本,一般為接口添加個version的參數。
8.json數據類型
- Number:整數或浮點數
- String:字符串
- Boolean:true 或 false
- Array:數組包含在方括號[]中
- Object:對象包含在大括號{}中
- Null:空類型
返回的數據結構
{
code:0,
message: "success",
data: { key1: value1, key2: value2, ... }
}
- code: 返回碼,0表示成功,非0表示各種不同的錯誤
- message: 描述信息,成功時為"success",錯誤時則是錯誤信息
- data: 成功時返回的數據,類型為對象或數組
// 正確 data: { token: abcdedf } // 錯誤 data: abcdefg
9. 使用Http狀態碼處理錯誤
不同錯誤需要定義不同的返回碼,屬於客戶端的錯誤和服務端的錯誤也要區分,比如1XX表示客戶端的錯誤,2XX表示服務端的錯誤
如果你的API沒有錯誤處理是很難的,只是返回500和出錯堆棧不一定有用
Http狀態碼提供70個出錯,我們只要使用10個左右:
200 – OK – 一切正常
201 – OK – 新的資源已經成功創建
204 – OK – 資源已經成功擅長
304 – Not Modified – 客戶端使用緩存數據
400 – Bad Request – 請求無效,需要附加細節解釋如 "JSON無效"
401 – Unauthorized – 請求需要用戶驗證
403 – Forbidden – 服務器已經理解了請求,但是拒絕服務或這種請求的訪問是不允許的。
404 – Not found – 沒有發現該資源
422 – Unprocessable Entity – 只有服務器不能處理實體時使用,比如圖像不能被格式化,或者重要字段丟失。
500 – Internal Server Error – API開發者應該避免這種錯誤。
使用詳細的錯誤包裝錯誤:
{
"errors": [
{
"userMessage": "Sorry, the requested resource does not exist",
"internalMessage": "No car found in the database",
"code": 34,
"more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
}
]
}
10.允許覆蓋http方法
一些代理只支持POST 和 GET方法, 為了使用這些有限方法支持RESTful API,需要一種辦法覆蓋http原來的方法。
使用訂制的HTTP頭 X-HTTP-Method-Override 來覆蓋POST 方法.
Restful API 設計參考原則