restful最佳實(shí)踐--接口規(guī)范
為了前后端分工明確,對(duì)接流暢梢薪,確背闯埃可讀性和擴(kuò)展性以及高可用宇姚、一致性匈庭,特約定下述無(wú)狀態(tài)RESTful API規(guī)范:
簡(jiǎn)述
前后端分離意味著,前后端之間使? JSON 來(lái)交流浑劳,兩個(gè)開(kāi)發(fā)團(tuán)隊(duì)之間使? API 作為契約進(jìn)?交互阱持。從此,后臺(tái)選?的技術(shù)棧不影響前臺(tái)魔熏。當(dāng)我們決定需要前后端分離時(shí)衷咽,我們?nèi)匀贿€需要?對(duì)?系列的問(wèn)題:
- 是否?夠的安全?我們?cè)趺慈ゴ鎯?chǔ)?戶數(shù)據(jù)蒜绽,使? LocalStorage 的話镶骗,還要考慮加密。采?哪種認(rèn)證?式來(lái)讓?戶登錄滓窍,并保存相應(yīng)的狀態(tài)卖词?
- 是否有?夠的技術(shù)來(lái)?撐前后端分離?有沒(méi)有能?創(chuàng)建出符合 RESTful 風(fēng)格的API吏夯?
- 是否有能?維護(hù) API 接口此蜈?當(dāng)前端或者后臺(tái)需要修改接?時(shí),是否能輕松地修改噪生?前端和后臺(tái)兩個(gè)團(tuán)隊(duì)是不是很容易合作裆赵?是不是可以輕松地進(jìn)?聯(lián)調(diào)?
- 前后端職責(zé)是否能明確跺嗽?即:后臺(tái)提供數(shù)據(jù)战授,前端負(fù)責(zé)顯?。
- 是否建?了前端的錯(cuò)誤追蹤機(jī)制桨嫁?能否幫助我們快速地定位出問(wèn)題植兰。
前后端分離的核?:后臺(tái)提供數(shù)據(jù),前端負(fù)責(zé)顯?
前提
RESTful API 統(tǒng)一約束客戶端和服務(wù)器之間的接口璃吧。簡(jiǎn)化和分離系統(tǒng)架構(gòu)楣导,使每個(gè)模塊獨(dú)立!
- 請(qǐng)求中使用URI定位資源
- 用HTTP Verbs[動(dòng)詞](GET畜挨、POST筒繁、PUT、DELETE)描述操作(具體表現(xiàn)形式)
- 數(shù)據(jù)傳遞(默認(rèn))采用:
Content-Type: application/json; charset=utf-8
Rest
REST即表述性狀態(tài)傳遞(英文:Representational State Transfer巴元,簡(jiǎn)稱(chēng)REST)是Roy Fielding博士在2000年他的博士論文中提出來(lái)的一種軟件架構(gòu)風(fēng)格毡咏。它是一種針對(duì)網(wǎng)絡(luò)應(yīng)用的設(shè)計(jì)和開(kāi)發(fā)方式,可以降低開(kāi)發(fā)的復(fù)雜性逮刨,提高系統(tǒng)的可伸縮性呕缭。REST是設(shè)計(jì)風(fēng)格而不是標(biāo)準(zhǔn)。REST通常基于使用HTTP臊旭,URI落恼,和XML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)子集)以及HTML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用)
統(tǒng)一接口(Uniform Interface)
統(tǒng)一接口約束定義客戶端和服務(wù)器之間的接口。它簡(jiǎn)化了分離的結(jié)構(gòu)离熏,使各部分獨(dú)立發(fā)展佳谦。
無(wú)狀態(tài)(Stateless)
REST要求狀態(tài)要么被放入資源狀態(tài)中,要么保存在客戶端上滋戳∽昝铮或者換句話說(shuō),服務(wù)器端不能保持除了單次請(qǐng)求之外的奸鸯,任何與其通信的客戶端的通信狀態(tài)咪笑。從客戶端的每個(gè)請(qǐng)求要包含服務(wù)器所需要的所有信息。這樣做的最直接的理由就是可伸縮性—— 如果服務(wù)器需要保持客戶端狀態(tài)娄涩,那么大量的客戶端交互會(huì)嚴(yán)重影響服務(wù)器的內(nèi)存可用空間(footprint)窗怒。
緩存(Cachable)
服務(wù)器返回信息必須被標(biāo)記是否可以緩存,如果緩存蓄拣,客戶端可能會(huì)重用之前的信息發(fā)送請(qǐng)求扬虚。
客戶-服務(wù)器(Client-Server)
客戶端無(wú)需關(guān)注數(shù)據(jù)存儲(chǔ),服務(wù)器端無(wú)需關(guān)注用戶界面球恤,提高了前后端可移植性辜昵。
分層系統(tǒng)(Layered System)
客戶端不關(guān)心直接連接到最終服務(wù)器還是連接到中間服務(wù)器。中間服務(wù)器可以通過(guò)啟用負(fù)載平衡和提供共享緩存來(lái)提高系統(tǒng)可擴(kuò)展性咽斧。分層系統(tǒng)也可以執(zhí)行安全策略堪置。
支持按需代碼(Code on Demand,可選)
服務(wù)器可以通過(guò)傳輸邏輯來(lái)臨時(shí)擴(kuò)展或定制客戶端的功能张惹。
URL規(guī)范
GET https//domain.com/api/{模塊名}/{?菜單名}/{接口名}/:param
不能使用大寫(xiě)舀锨,用中橫線 - 不用下劃線 _ ;
使用名詞表示資源集合宛逗,使用復(fù)數(shù)形式(為確保所有API URIs保持一致)坎匿,不能使用動(dòng)詞;
每個(gè)資源都至少有一個(gè)標(biāo)識(shí)它的URI拧额,同時(shí)應(yīng)該遵循一個(gè)可預(yù)測(cè)的層次結(jié)構(gòu)來(lái)提高可理解性碑诉,從而提高可用性彪腔;
-
無(wú)需在URI中增加版本號(hào)侥锦,通過(guò)HTTP請(qǐng)求頭信息的字段中進(jìn)行區(qū)分(或者在URI包含主版本信息,同時(shí)請(qǐng)求頭包含子版本信息德挣。
Accept: vnd.example-com.foo+json; version=1.1 Accept: vnd.example-com.foo+json; version=2.0
Request
請(qǐng)求方法 | 說(shuō)明 | 安全性 | 冪等性 |
---|---|---|---|
GET(SELECT) | 獲取資源 | ?? | ?? |
POST(CREATE) | 創(chuàng)建資源 | ? | ? |
PUT(UPDATE) | 替換(新增或完整更新) | ? | ?? |
DELETE(DELETE) | 刪除資源 | ? | ?? |
PATCH | 是對(duì) PUT 方法的補(bǔ)充恭垦,用來(lái)對(duì)已知資源進(jìn)行局部更新 。 | ? | ?? |
OPTIONS | 用于url驗(yàn)證,驗(yàn)證接口服務(wù)是否正常 | ?? | ?? |
TRACE | 回顯服務(wù)器收到的請(qǐng)求番挺,主要用于測(cè)試或診斷 | ?? | ?? |
說(shuō)明:
安全性 :不會(huì)改變資源狀態(tài)唠帝,可以理解為只讀的;
冪等性 :執(zhí)行1次和執(zhí)行N次玄柏,對(duì)資源狀態(tài)改變的效果是等價(jià)的襟衰。
查詢(xún)字段內(nèi)容過(guò)多,統(tǒng)一使用POST方式查詢(xún)粪摘,請(qǐng)求地址增加/query加以區(qū)分
-
批量刪除瀑晒,統(tǒng)一使用POST方式,請(qǐng)求地址增加/delete加以區(qū)分
由于存在批量刪除的情況徘意,而一些網(wǎng)關(guān)苔悦、代理、防火墻在收到DELETE請(qǐng)求后椎咧,會(huì)把請(qǐng)求的body直接剝離掉玖详。建議將存在批量刪除的接口統(tǒng)一改成POST提交,為了標(biāo)識(shí)是刪除操作勤讽,在請(qǐng)求路徑上增加/delete蟋座。
GET
被用于獲取資源。不允許對(duì)服務(wù)器上資源做任何修改操作地技。
示例:
GET http://www.example.com/customers/12345
GET http://www.example.com/customers/12345/orders
GET http://www.example.com/buckets/sample
PUT
常用于更新資源蜈七。通過(guò)請(qǐng)求體攜帶資源發(fā)送給服務(wù)器。注意:在資源ID由客戶端而不是由服務(wù)器選擇的情況下莫矗,也可以使用PUT來(lái)創(chuàng)建資源飒硅。修改成功返回200,創(chuàng)建成功返回201作谚。建議使用post進(jìn)行創(chuàng)建新資源三娩。
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
常用于創(chuàng)建新資源。創(chuàng)建成功通常返回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列表眨唬。 可用于分頁(yè)会前、排序、過(guò)濾匾竿。 | 200 (OK)瓦宜,單個(gè)customer。如果id不存在或非法岭妖,返回404 (NotFound)临庇。 |
PUT | 404 (Not Found)反璃,除非你想更新整個(gè)資源 | 200 (OK) 或者204 (No Content)。如果id不存在或非法假夺,返回404 (NotFound)淮蜈。 |
POST | 201 (Created) | 404 (Not Found) |
DELETE | 404 (Not Found),除非你想刪除整個(gè)資源 | 200 (OK) 已卷。如果id不存在或非法梧田,返回404 (NotFound)。 |
其他
-
排序
使用數(shù)組傳遞排序字段侧蘸,-
表示降序柿扣,無(wú)任何標(biāo)識(shí)表示升序。sorts: ['-age', 'name']
-
時(shí)間傳遞
日期和時(shí)間戳如果沒(méi)有適當(dāng)和一致地處理闺魏,可能是一個(gè)真正的頭痛未状。建議使用UTC或GMT時(shí)間存儲(chǔ),處理析桥,緩存等時(shí)間戳或者使用統(tǒng)一格式化的時(shí)間字符串”yyyy-MM-dd HH:mm:ss”
Respone
狀態(tài)碼
狀態(tài)碼 | 說(shuō)明 |
---|---|
200 OK | 服務(wù)器成功返回請(qǐng)求的數(shù)據(jù) |
201 CREATED | 新建或修改數(shù)據(jù)成功 |
202 Accepted | 表示一個(gè)請(qǐng)求已經(jīng)進(jìn)入后臺(tái)排隊(duì)(異步任務(wù)) |
204 NO CONTENT | 刪除數(shù)據(jù)成功 |
400 INVALID REQUEST | 請(qǐng)求有錯(cuò)誤司草,服務(wù)器沒(méi)有進(jìn)行新建或修改數(shù)據(jù)的操作(冪等操作) |
401 Unauthorized | 沒(méi)有權(quán)限(令牌、用戶名泡仗、密碼錯(cuò)誤) |
403 Forbidden | 得到授權(quán)(與401錯(cuò)誤相對(duì))埋虹,但是訪問(wèn)是被禁止的 |
404 NOT FOUND | 請(qǐng)求記錄不存在,服務(wù)器沒(méi)有進(jìn)行操作(冪等操作) |
406 Not Acceptable | 請(qǐng)求的格式不符合(比如用戶請(qǐng)求JSON格式娩怎,但是只有XML格式) |
500 INTERNAL SERVER ERROR | 服務(wù)器發(fā)生錯(cuò)誤搔课,無(wú)法判斷發(fā)出的請(qǐng)求是否成功 |
格式
- 前后端交互字段全部使用小駝峰方式
{
"code": "200", // HTTP響應(yīng)碼(好多javascript框架并不會(huì)獲取http狀態(tài)碼,所以包裝到body中便于使用)
"status": "success/fail/error", // 見(jiàn)下述表格
"content/data": []/{}, // 多條記錄使用JSON數(shù)組截亦,單條記錄使用JSON對(duì)象
"message": [] // 狀態(tài)為error或fail時(shí)爬泥,對(duì)應(yīng)的錯(cuò)誤信息
}
status說(shuō)明
狀態(tài) | 說(shuō)明 |
---|---|
fail | 返回碼為 500-599 |
error | 返回碼為 400-499 |
success | 其他狀態(tài)碼(1xx、2xx崩瓤、3xx) |
---------------------------------------------------------------------------分割線-----------------------------------------------------------
1.后端應(yīng)考慮接口請(qǐng)方式袍啡,現(xiàn)在使用統(tǒng)一方式post
2.后端定義前端傳輸字段要符合駝峰命名如:storeName;見(jiàn)名知意;后臺(tái)返回字段也需符合駝峰命名
3.接口文檔對(duì)應(yīng)字段應(yīng)和后端返回一致(后端可以小心點(diǎn))
4. 后臺(tái)返回?cái)?shù)據(jù)字段需都在data里,不得在data之外幼东;除與前端商定過(guò)
5. 后臺(tái)返回值為空時(shí),需返回相對(duì)應(yīng)的鍵名如:{listData: null} (鍵值為空時(shí)值null)
6. 接口功能獨(dú)立應(yīng)分拆成新的接口
7. 返回字段須有msg,必須有值
{
"code":200, // 1.成功為200嗅剖, 2.其他非200
"data": {
"id":"1001",
"name":"張三",
"age":"20"
},
"msg":"成功", // 1.成功信息, 2其他返回對(duì)應(yīng)信息
}
示例
請(qǐng)求方式:POST
參數(shù):說(shuō)明
字段 | 類(lèi)型 | 說(shuō)明 | 必需 |
---|---|---|---|
token | string | token信息 | 是 |
oldPwd | string | 舊密碼(hash) | 是 |
newPwd | string | 新密碼(hash) | 是 |
返回值:
字段 | 類(lèi)型 | 說(shuō)明 | 必需 |
---|---|---|---|
code | int | 返回的狀態(tài)碼 | 是 |
data | Object/Array | 返回類(lèi)型(值為空時(shí)返回null) | 是 |
msg | string | 返回信息 | 是 |
示例1
正確的
{
"code":200, // 1.成功為200嘁扼, 2.其他非200
"data": {
"userInfo":{
"id":null, // 數(shù)據(jù)類(lèi)型String,空時(shí)為null
"name":"張三",
"age":20 , // 數(shù)據(jù)類(lèi)型為Number, 空時(shí)為null,
"imgUrls": ['地址1'信粮, '地址2'] //類(lèi)型Array, 空時(shí)為null
"photoUrls": null
},
"level": :"領(lǐng)導(dǎo)"
},
"page": { //類(lèi)型:Object 必有字段 備注:分頁(yè)信息
"total":1, //類(lèi)型:Number 必有字段 備注:總條數(shù)
"pages":1 //類(lèi)型:Number 必有字段 備注:總頁(yè)數(shù)
},
"msg":"成功", // 1.成功信息, 2其他返回對(duì)應(yīng)信息
}
錯(cuò)誤的
{
"code":200, // 1.成功為200偷拔, 2.其他非200
"data": {
"userInfo":{
},
"other":{
"ohterIfno": "小李子"
}
},
"level": "領(lǐng)導(dǎo)", // 錯(cuò)誤格式
"msg":"成功", // 1.成功信息蒋院, 2其他返回對(duì)應(yīng)信息
}