restful接口設(shè)計(jì)規(guī)范總結(jié)
這篇 文章主要是借鑒他人,但是自己很想總結(jié)出一套規(guī)范嫡霞,以供向我這樣的新手使用,用來(lái)規(guī)范代碼希柿,如果有什么好的提議诊沪,請(qǐng)不吝賜教,本篇文章長(zhǎng)期更新曾撤!
一端姚、重要概念:
REST,即Representational State Transfer的縮寫(xiě)。我對(duì)這個(gè)詞組的翻譯是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"盾戴。
Resource(資源) :對(duì)象的單個(gè)實(shí)例寄锐。 例如,一只動(dòng)物尖啡。它可以是一段文本、一張圖片剩膘、一首歌曲衅斩、一種服務(wù),總之就是一個(gè)具體的實(shí)在怠褐。你可以用一個(gè)URI(統(tǒng)一資源定位符)指向它畏梆,每種資源對(duì)應(yīng)一個(gè)特定的URI。要獲取這個(gè)資源奈懒,訪問(wèn)它的URI就可以奠涌,因此URI就成了每一個(gè)資源的地址或獨(dú)一無(wú)二的識(shí)別符。
集合:對(duì)象的集合磷杏。 例如溜畅,動(dòng)物。
第三方:使用我們接口的開(kāi)發(fā)者
表現(xiàn)層(Representation)
"資源"是一種信息實(shí)體极祸,它可以有多種外在表現(xiàn)形式慈格。我們把"資源"具體呈現(xiàn)出來(lái)的形式怠晴,叫做它的"表現(xiàn)層"(Representation)。
狀態(tài)轉(zhuǎn)化(State Transfer)
訪問(wèn)一個(gè)網(wǎng)站浴捆,就代表了客戶(hù)端和服務(wù)器的一個(gè)互動(dòng)過(guò)程蒜田。在這個(gè)過(guò)程中,勢(shì)必涉及到數(shù)據(jù)和狀態(tài)的變化选泻〕逶粒互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個(gè)無(wú)狀態(tài)協(xié)議页眯。這意味著色解,所有的狀態(tài)都保存在服務(wù)器端。因此餐茵,如果客戶(hù)端想要操作服務(wù)器科阎,必須通過(guò)某種手段,讓服務(wù)器端發(fā)生"狀態(tài)轉(zhuǎn)化"(State Transfer)忿族。而這種轉(zhuǎn)化是建立在表現(xiàn)層之上的锣笨,所以就是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
客戶(hù)端用到的手段道批,只能是HTTP協(xié)議错英。具體來(lái)說(shuō),就是HTTP協(xié)議里面隆豹,四個(gè)表示操作方式的動(dòng)詞:GET椭岩、POST、PUT璃赡、DELETE判哥。它們分別對(duì)應(yīng)四種基本操作:GET用來(lái)獲取資源,POST用來(lái)新建資源(也可以用于更新資源)碉考,PUT用來(lái)更新資源塌计,DELETE用來(lái)刪除資源。
比如侯谁,文本可以用txt格式表現(xiàn)锌仅,也可以用HTML格式、XML格式墙贱、JSON格式表現(xiàn)热芹,甚至可以采用二進(jìn)制格式;圖片可以用JPG格式表現(xiàn)惨撇,也可以用PNG格式表現(xiàn)伊脓。
URI只代表資源的實(shí)體,不代表它的形式串纺。嚴(yán)格地說(shuō)丽旅,有些網(wǎng)址最后的".html"后綴名是不必要的椰棘,因?yàn)檫@個(gè)后綴名表示格式,屬于"表現(xiàn)層"范疇榄笙,而URI應(yīng)該只代表"資源"的位置邪狞。它的具體表現(xiàn)形式,應(yīng)該在HTTP請(qǐng)求的頭信息中用Accept和Content-Type字段指定茅撞,這兩個(gè)字段才是對(duì)"表現(xiàn)層"的描述帆卓。
綜合上面的解釋?zhuān)覀兛偨Y(jié)一下什么是RESTful架構(gòu):
(1)每一個(gè)URI代表一種資源;
(2)客戶(hù)端和服務(wù)器之間米丘,傳遞這種資源的某種表現(xiàn)層剑令;
(3)客戶(hù)端通過(guò)四個(gè)HTTP動(dòng)詞,對(duì)服務(wù)器端資源進(jìn)行操作拄查,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"吁津。
二、REST接口規(guī)范
1堕扶、動(dòng)作
GET (SELECT):從服務(wù)器檢索特定資源碍脏,或資源列表。
POST (CREATE):在服務(wù)器上創(chuàng)建一個(gè)新的資源稍算。
PUT (UPDATE):更新服務(wù)器上的資源典尾,提供整個(gè)資源。
PATCH (UPDATE):更新服務(wù)器上的資源糊探,僅提供更改的屬性钾埂。
DELETE (DELETE):從服務(wù)器刪除資源。
首先是四個(gè)半種動(dòng)作:
post科平、delete褥紫、put/patch、get
因?yàn)閜ut/patch只能算作一類(lèi)匠抗,所以將patch歸為半個(gè)故源。
另外還有有兩個(gè)較少知名的HTTP動(dòng)詞:
HEAD - 檢索有關(guān)資源的元數(shù)據(jù),例如數(shù)據(jù)的哈瞎常或上次更新時(shí)間。
OPTIONS - 檢索關(guān)于客戶(hù)端被允許對(duì)資源做什么的信息印机。
2矢腻、路徑(接口命名)
路徑又稱(chēng)"終點(diǎn)"(endpoint),表示API的具體網(wǎng)址射赛。
在RESTful架構(gòu)中多柑,每個(gè)網(wǎng)址代表一種資源(resource),所以網(wǎng)址中不能有動(dòng)詞楣责,只能有名詞竣灌,而且所用的名詞往往與數(shù)據(jù)庫(kù)的表格名對(duì)應(yīng)聂沙。一般來(lái)說(shuō),數(shù)據(jù)庫(kù)中的表都是同種記錄的"集合"(collection)初嘹,所以API中的名詞也應(yīng)該使用復(fù)數(shù)及汉。
舉例來(lái)說(shuō),有一個(gè)API提供動(dòng)物園(zoo)的信息屯烦,還包括各種動(dòng)物和雇員的信息坷随,則它的路徑應(yīng)該設(shè)計(jì)成下面這樣。
接口盡量使用名詞驻龟,禁止使用動(dòng)詞温眉,下面是一些例子。
GET /zoos:列出所有動(dòng)物園
POST /zoos:新建一個(gè)動(dòng)物園
GET /zoos/ID:獲取某個(gè)指定動(dòng)物園的信息
PUT /zoos/ID:更新某個(gè)指定動(dòng)物園的信息(提供該動(dòng)物園的全部信息)
PATCH /zoos/ID:更新某個(gè)指定動(dòng)物園的信息(提供該動(dòng)物園的部分信息)
DELETE /zoos/ID:刪除某個(gè)動(dòng)物園
GET /zoos/ID/animals:列出某個(gè)指定動(dòng)物園的所有動(dòng)物
DELETE /zoos/ID/animals/ID:刪除某個(gè)指定動(dòng)物園的指定動(dòng)物
反例:
/getAllCars
/createNewCar
/deleteAllRedCars
再比如翁狐,某個(gè)URI是/posts/show/1类溢,其中show是動(dòng)詞,這個(gè)URI就設(shè)計(jì)錯(cuò)了露懒,正確的寫(xiě)法應(yīng)該是/posts/1闯冷,然后用GET方法表示show。
如果某些動(dòng)作是HTTP動(dòng)詞表示不了的隐锭,你就應(yīng)該把動(dòng)作做成一種資源窃躲。比如網(wǎng)上匯款,從賬戶(hù)1向賬戶(hù)2匯款500元钦睡,錯(cuò)誤的URI是:
POST /accounts/1/transfer/500/to/2
正確的寫(xiě)法是把動(dòng)詞transfer改成名詞transaction蒂窒,資源不能是動(dòng)詞,但是可以是一種服務(wù):
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
理清資源的層次結(jié)構(gòu)荞怒,比如業(yè)務(wù)針對(duì)的范圍是學(xué)校洒琢,那么學(xué)校會(huì)是一級(jí)資源(/school),老師(/school/teachers)褐桌,學(xué)生(/school/students)就是二級(jí)資源衰抑。
3、版本(Versioning)
應(yīng)該將API的版本號(hào)放入U(xiǎn)RL荧嵌。如:
https://api.example.com/v1/
另一種做法是呛踊,將版本號(hào)放在HTTP頭信息中,但不如放入U(xiǎn)RL方便和直觀啦撮。Github采用這種做法谭网。
4、過(guò)濾信息(Filtering)
如果記錄數(shù)量很多赃春,服務(wù)器不可能都將它們返回給用戶(hù)愉择。API應(yīng)該提供參數(shù),過(guò)濾返回結(jié)果。
下面是一些常見(jiàn)的參數(shù)锥涕。
?limit=10:指定返回記錄的數(shù)量
?offset=10:指定返回記錄的開(kāi)始位置衷戈。
?page_number=2&page_size=100:指定第幾頁(yè),以及每頁(yè)的記錄數(shù)层坠。
?sortby=name&order=asc:指定返回結(jié)果按照哪個(gè)屬性排序殖妇,以及排序順序。
?animal_type_id=1:指定篩選條件
參數(shù)的設(shè)計(jì)允許存在冗余窿春,即允許API路徑和URL參數(shù)偶爾有重復(fù)拉一。比如,
GET /zoo/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的旧乞。
5蔚润、狀態(tài)碼(Status Codes)
狀態(tài)碼范圍
1xx 信息,請(qǐng)求收到尺栖,繼續(xù)處理嫡纠。范圍保留用于底層HTTP的東西,你很可能永遠(yuǎn)也用不到延赌。
2xx 成功除盏,行為被成功地接受、理解和采納
3xx 重定向挫以,為了完成請(qǐng)求者蠕,必須進(jìn)一步執(zhí)行的動(dòng)作
4xx 客戶(hù)端錯(cuò)誤,請(qǐng)求包含語(yǔ)法錯(cuò)誤或者請(qǐng)求無(wú)法實(shí)現(xiàn)掐松。范圍保留用于響應(yīng)客戶(hù)端做出的錯(cuò)誤踱侣,例如。他們提供不良數(shù)據(jù)或要求不存在的東西大磺。這些請(qǐng)求應(yīng)該是冪等的抡句,而不是更改服務(wù)器的狀態(tài)。
5xx 范圍的狀態(tài)碼是保留給服務(wù)器端錯(cuò)誤用的杠愧。這些錯(cuò)誤常常是從底層的函數(shù)拋出來(lái)的待榔,甚至
開(kāi)發(fā)人員也通常沒(méi)法處理,發(fā)送這類(lèi)狀態(tài)碼的目的以確绷骷茫客戶(hù)端獲得某種響應(yīng)锐锣。
當(dāng)收到5xx響應(yīng)時(shí),客戶(hù)端不可能知道服務(wù)器的狀態(tài)绳瘟,所以這類(lèi)狀態(tài)碼是要盡可能的避免刺下。
服務(wù)器向用戶(hù)返回的狀態(tài)碼和提示信息,常見(jiàn)的有以下一些(方括號(hào)中是該狀態(tài)碼對(duì)應(yīng)的HTTP動(dòng)詞)稽荧。
200 OK - [GET]:服務(wù)器成功返回用戶(hù)請(qǐng)求的數(shù)據(jù),該操作是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶(hù)新建或修改數(shù)據(jù)成功姨丈。
202 Accepted - [*]:表示一個(gè)請(qǐng)求已經(jīng)進(jìn)入后臺(tái)排隊(duì)(異步任務(wù))
204 NO CONTENT - [DELETE]:用戶(hù)刪除數(shù)據(jù)成功畅卓。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶(hù)發(fā)出的請(qǐng)求有錯(cuò)誤,服務(wù)器沒(méi)有進(jìn)行新建或修改數(shù)據(jù)的操作蟋恬,該操作是冪等的翁潘。
401 Unauthorized - [*]:表示用戶(hù)沒(méi)有權(quán)限(令牌、用戶(hù)名歼争、密碼錯(cuò)誤)拜马。
403 Forbidden - [*] 表示用戶(hù)得到授權(quán)(與401錯(cuò)誤相對(duì)),但是訪問(wèn)是被禁止的沐绒。
404 NOT FOUND - [*]:用戶(hù)發(fā)出的請(qǐng)求針對(duì)的是不存在的記錄俩莽,服務(wù)器沒(méi)有進(jìn)行操作,該操作是冪等的乔遮。
406 Not Acceptable - [GET]:用戶(hù)請(qǐng)求的格式不可得(比如用戶(hù)請(qǐng)求JSON格式扮超,但是只有XML格式)。
410 Gone -[GET]:用戶(hù)請(qǐng)求的資源被永久刪除蹋肮,且不會(huì)再得到的出刷。
422 Unprocesable entity - [POST/PUT/PATCH] 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),發(fā)生一個(gè)驗(yàn)證錯(cuò)誤坯辩。
500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯(cuò)誤馁龟,用戶(hù)將無(wú)法判斷發(fā)出的請(qǐng)求是否成功。
502 網(wǎng)關(guān)錯(cuò)誤
503 Service Unavailable
504 網(wǎng)關(guān)超時(shí)
參考資料:
RESTful API 設(shè)計(jì)指南--阮一峰:http://www.ruanyifeng.com/blog/2014/05/restful_api.html