restful最佳實踐--接口規范
為了前后端分工明確,對接流暢,確保可讀性和擴展性以及高可用、一致性,特約定下述無狀態RESTful API規范:
簡述
前后端分離意味著,前后端之間使? JSON 來交流,兩個開發團隊之間使? API 作為契約進?交互。從此,后臺選?的技術棧不影響前臺。當我們決定需要前后端分離時,我們仍然還需要?對?系列的問題:
- 是否?夠的安全?我們怎么去存儲?戶數據,使? LocalStorage 的話,還要考慮加密。采?哪種認證?式來讓?戶登錄,并保存相應的狀態?
- 是否有?夠的技術來?撐前后端分離?有沒有能?創建出符合 RESTful 風格的API?
- 是否有能?維護 API 接口?當前端或者后臺需要修改接?時,是否能輕松地修改?前端和后臺兩個團隊是不是很容易合作?是不是可以輕松地進?聯調?
- 前后端職責是否能明確?即:后臺提供數據,前端負責顯?。
- 是否建?了前端的錯誤追蹤機制?能否幫助我們快速地定位出問題。
前后端分離的核?:后臺提供數據,前端負責顯?
前提
RESTful API 統一約束客戶端和服務器之間的接口。簡化和分離系統架構,使每個模塊獨立!
- 請求中使用URI定位資源
- 用HTTP Verbs[動詞](GET、POST、PUT、DELETE)描述操作(具體表現形式)
- 數據傳遞(默認)采用:
Content-Type: application/json; charset=utf-8
Rest
REST即表述性狀態傳遞(英文:Representational State Transfer,簡稱REST)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟件架構風格。它是一種針對網絡應用的設計和開發方式,可以降低開發的復雜性,提高系統的可伸縮性。REST是設計風格而不是標準。REST通常基于使用HTTP,URI,和XML(標準通用標記語言下的一個子集)以及HTML(標準通用標記語言下的一個應用)
統一接口(Uniform Interface)
統一接口約束定義客戶端和服務器之間的接口。它簡化了分離的結構,使各部分獨立發展。
無狀態(Stateless)
REST要求狀態要么被放入資源狀態中,要么保存在客戶端上。或者換句話說,服務器端不能保持除了單次請求之外的,任何與其通信的客戶端的通信狀態。從客戶端的每個請求要包含服務器所需要的所有信息。這樣做的最直接的理由就是可伸縮性—— 如果服務器需要保持客戶端狀態,那么大量的客戶端交互會嚴重影響服務器的內存可用空間(footprint)。
緩存(Cachable)
服務器返回信息必須被標記是否可以緩存,如果緩存,客戶端可能會重用之前的信息發送請求。
客戶-服務器(Client-Server)
客戶端無需關注數據存儲,服務器端無需關注用戶界面,提高了前后端可移植性。
分層系統(Layered System)
客戶端不關心直接連接到最終服務器還是連接到中間服務器。中間服務器可以通過啟用負載平衡和提供共享緩存來提高系統可擴展性。分層系統也可以執行安全策略。
支持按需代碼(Code on Demand,可選)
服務器可以通過傳輸邏輯來臨時擴展或定制客戶端的功能。
URL規范
GET https//domain.com/api/{模塊名}/{?菜單名}/{接口名}/:param
不能使用大寫,用中橫線 - 不用下劃線 _ ;
使用名詞表示資源集合,使用復數形式(為確保所有API URIs保持一致),不能使用動詞;
每個資源都至少有一個標識它的URI,同時應該遵循一個可預測的層次結構來提高可理解性,從而提高可用性;
-
無需在URI中增加版本號,通過HTTP請求頭信息的字段中進行區分(或者在URI包含主版本信息,同時請求頭包含子版本信息。
Accept: vnd.example-com.foo+json; version=1.1 Accept: vnd.example-com.foo+json; version=2.0
Request
請求方法 | 說明 | 安全性 | 冪等性 |
---|---|---|---|
GET(SELECT) | 獲取資源 | ?? | ?? |
POST(CREATE) | 創建資源 | ? | ? |
PUT(UPDATE) | 替換(新增或完整更新) | ? | ?? |
DELETE(DELETE) | 刪除資源 | ? | ?? |
PATCH | 是對 PUT 方法的補充,用來對已知資源進行局部更新 。 | ? | ?? |
OPTIONS | 用于url驗證,驗證接口服務是否正常 | ?? | ?? |
TRACE | 回顯服務器收到的請求,主要用于測試或診斷 | ?? | ?? |
說明:
安全性 :不會改變資源狀態,可以理解為只讀的;
冪等性 :執行1次和執行N次,對資源狀態改變的效果是等價的。
查詢字段內容過多,統一使用POST方式查詢,請求地址增加/query加以區分
-
批量刪除,統一使用POST方式,請求地址增加/delete加以區分
由于存在批量刪除的情況,而一些網關、代理、防火墻在收到DELETE請求后,會把請求的body直接剝離掉。建議將存在批量刪除的接口統一改成POST提交,為了標識是刪除操作,在請求路徑上增加/delete。
GET
被用于獲取資源。不允許對服務器上資源做任何修改操作。
示例:
GET http://www.example.com/customers/12345
GET http://www.example.com/customers/12345/orders
GET http://www.example.com/buckets/sample
PUT
常用于更新資源。通過請求體攜帶資源發送給服務器。注意:在資源ID由客戶端而不是由服務器選擇的情況下,也可以使用PUT來創建資源。修改成功返回200,創建成功返回201。建議使用post進行創建新資源。
PUT http://www.example.com/customers/12345
PUT http://www.example.com/customers/12345/orders/98765
PUT http://www.example.com/buckets/secret_stuff
POST
常用于創建新資源。創建成功通常返回201。
POST http://www.example.com/customers
POST http://www.example.com/customers/12345/orders
DELETE
刪除資源。
DELETE http://www.example.com/customers/12345
DELETE http://www.example.com/customers/12345/orders
DELETE http://www.example.com/buckets/sample
HTTP Verb | /customers | /customers/{id} |
---|---|---|
GET | 200 (OK),customers列表。 可用于分頁、排序、過濾。 | 200 (OK),單個customer。如果id不存在或非法,返回404 (NotFound)。 |
PUT | 404 (Not Found),除非你想更新整個資源 | 200 (OK) 或者204 (No Content)。如果id不存在或非法,返回404 (NotFound)。 |
POST | 201 (Created) | 404 (Not Found) |
DELETE | 404 (Not Found),除非你想刪除整個資源 | 200 (OK) 。如果id不存在或非法,返回404 (NotFound)。 |
其他
-
排序
使用數組傳遞排序字段,-
表示降序,無任何標識表示升序。sorts: ['-age', 'name']
-
時間傳遞
日期和時間戳如果沒有適當和一致地處理,可能是一個真正的頭痛。建議使用UTC或GMT時間存儲,處理,緩存等時間戳或者使用統一格式化的時間字符串”yyyy-MM-dd HH:mm:ss”
Respone
狀態碼
狀態碼 | 說明 |
---|---|
200 OK | 服務器成功返回請求的數據 |
201 CREATED | 新建或修改數據成功 |
202 Accepted | 表示一個請求已經進入后臺排隊(異步任務) |
204 NO CONTENT | 刪除數據成功 |
400 INVALID REQUEST | 請求有錯誤,服務器沒有進行新建或修改數據的操作(冪等操作) |
401 Unauthorized | 沒有權限(令牌、用戶名、密碼錯誤) |
403 Forbidden | 得到授權(與401錯誤相對),但是訪問是被禁止的 |
404 NOT FOUND | 請求記錄不存在,服務器沒有進行操作(冪等操作) |
406 Not Acceptable | 請求的格式不符合(比如用戶請求JSON格式,但是只有XML格式) |
500 INTERNAL SERVER ERROR | 服務器發生錯誤,無法判斷發出的請求是否成功 |
格式
- 前后端交互字段全部使用小駝峰方式
{
"code": "200", // HTTP響應碼(好多javascript框架并不會獲取http狀態碼,所以包裝到body中便于使用)
"status": "success/fail/error", // 見下述表格
"content/data": []/{}, // 多條記錄使用JSON數組,單條記錄使用JSON對象
"message": [] // 狀態為error或fail時,對應的錯誤信息
}
status說明
狀態 | 說明 |
---|---|
fail | 返回碼為 500-599 |
error | 返回碼為 400-499 |
success | 其他狀態碼(1xx、2xx、3xx) |
---------------------------------------------------------------------------分割線-----------------------------------------------------------
1.后端應考慮接口請方式,現在使用統一方式post
2.后端定義前端傳輸字段要符合駝峰命名如:storeName;見名知意;后臺返回字段也需符合駝峰命名
3.接口文檔對應字段應和后端返回一致(后端可以小心點)
4. 后臺返回數據字段需都在data里,不得在data之外;除與前端商定過
5. 后臺返回值為空時,需返回相對應的鍵名如:{listData: null} (鍵值為空時值null)
6. 接口功能獨立應分拆成新的接口
7. 返回字段須有msg,必須有值
{
"code":200, // 1.成功為200, 2.其他非200
"data": {
"id":"1001",
"name":"張三",
"age":"20"
},
"msg":"成功", // 1.成功信息, 2其他返回對應信息
}
示例
請求方式:POST
參數:說明
字段 | 類型 | 說明 | 必需 |
---|---|---|---|
token | string | token信息 | 是 |
oldPwd | string | 舊密碼(hash) | 是 |
newPwd | string | 新密碼(hash) | 是 |
返回值:
字段 | 類型 | 說明 | 必需 |
---|---|---|---|
code | int | 返回的狀態碼 | 是 |
data | Object/Array | 返回類型(值為空時返回null) | 是 |
msg | string | 返回信息 | 是 |
示例1
正確的
{
"code":200, // 1.成功為200, 2.其他非200
"data": {
"userInfo":{
"id":null, // 數據類型String,空時為null
"name":"張三",
"age":20 , // 數據類型為Number, 空時為null,
"imgUrls": ['地址1', '地址2'] //類型Array, 空時為null
"photoUrls": null
},
"level": :"領導"
},
"page": { //類型:Object 必有字段 備注:分頁信息
"total":1, //類型:Number 必有字段 備注:總條數
"pages":1 //類型:Number 必有字段 備注:總頁數
},
"msg":"成功", // 1.成功信息, 2其他返回對應信息
}
錯誤的
{
"code":200, // 1.成功為200, 2.其他非200
"data": {
"userInfo":{
},
"other":{
"ohterIfno": "小李子"
}
},
"level": "領導", // 錯誤格式
"msg":"成功", // 1.成功信息, 2其他返回對應信息
}