restful風(fēng)格的API

1.什么是rest?

REST全稱是Representational State Transfer你虹,中文意思是表述(編者注:通常譯為表征)性狀態(tài)轉(zhuǎn)移构眯。 它首次出現(xiàn)在2000年Roy Fielding的博士論文中裆熙,Roy Fielding是HTTP規(guī)范的主要編寫者之一邓夕。 他在論文中提到:"我這篇文章的寫作目的掰茶,就是想在符合架構(gòu)原理的前提下萤厅,理解和評(píng)估以網(wǎng)絡(luò)為基礎(chǔ)的應(yīng)用軟件的架構(gòu)設(shè)計(jì)橄抹,得到一個(gè)功能強(qiáng)、性能好惕味、適宜通信的架構(gòu)楼誓。REST指的是一組架構(gòu)約束條件和原則。" 如果一個(gè)架構(gòu)符合REST的約束條件和原則名挥,我們就稱它為RESTful架構(gòu)疟羹。
REST本身并沒有創(chuàng)造新的技術(shù)、組件或服務(wù)禀倔,而隱藏在RESTful背后的理念就是使用Web的現(xiàn)有特征和能力榄融, 更好地使用現(xiàn)有Web標(biāo)準(zhǔn)中的一些準(zhǔn)則和約束。雖然REST本身受Web技術(shù)的影響很深救湖, 但是理論上REST架構(gòu)風(fēng)格并不是綁定在HTTP上剃袍,只不過(guò)目前HTTP是唯一與REST相關(guān)的實(shí)例。 所以我們這里描述的REST也是通過(guò)HTTP實(shí)現(xiàn)的REST捎谨。

2.什么是RESTful

REST 指的是一組架構(gòu)約束條件和原則民效。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計(jì)就是 RESTful憔维。

Web 應(yīng)用程序最重要的 REST 原則是,客戶端和服務(wù)器之間的交互在請(qǐng)求之間是無(wú)狀態(tài)的畏邢。從客戶端到服務(wù)器的每個(gè)請(qǐng)求都必須包含理解請(qǐng)求所必需的信息业扒。如果服務(wù)器在請(qǐng)求之間的任何時(shí)間點(diǎn)重啟,客戶端不會(huì)得到通知舒萎。此外程储,無(wú)狀態(tài)請(qǐng)求可以由任何可用服務(wù)器回答,這十分適合云計(jì)算之類的環(huán)境臂寝≌吕穑客戶端可以緩存數(shù)據(jù)以改進(jìn)性能。
在服務(wù)器端咆贬,應(yīng)用程序狀態(tài)和功能可以分為各種資源败徊。資源是一個(gè)有趣的概念實(shí)體,它向客戶端公開掏缎。資源的例子有:應(yīng)用程序?qū)ο笾灞摹?shù)據(jù)庫(kù)記錄、算法等等眷蜈。每個(gè)資源都使用 URI (Universal Resource Identifier) 得到一個(gè)唯一的地址沪哺。所有資源都共享統(tǒng)一的接口,以便在客戶端和服務(wù)器之間傳輸狀態(tài)酌儒。使用的是標(biāo)準(zhǔn)的 HTTP 方法辜妓,比如 GET、PUT忌怎、POST 和 DELETE嫌拣。Hypermedia是應(yīng)用程序狀態(tài)的引擎,資源表示通過(guò)超鏈接互聯(lián)呆躲。
另一個(gè)重要的 REST 原則是分層系統(tǒng),這表示組件無(wú)法了解它與之交互的中間層以外的組件捶索。通過(guò)將系統(tǒng)知識(shí)限制在單個(gè)層弟孟,可以限制整個(gè)系統(tǒng)的復(fù)雜性别惦,促進(jìn)了底層的獨(dú)立性。
當(dāng) REST 架構(gòu)的約束條件作為一個(gè)整體應(yīng)用時(shí),將生成一個(gè)可以擴(kuò)展到大量客戶端的應(yīng)用程序绪励。它還降低了客戶端和服務(wù)器之間的交互延遲。統(tǒng)一界面簡(jiǎn)化了整個(gè)系統(tǒng)架構(gòu)址芯,改進(jìn)了子系統(tǒng)之間交互的可見性哥捕。REST 簡(jiǎn)化了客戶端和服務(wù)器的實(shí)現(xiàn)。

3.url(統(tǒng)一資源定位符)的設(shè)計(jì)

  • 動(dòng)詞 + 賓語(yǔ)
    RESTful 的核心思想就是构回,客戶端發(fā)出的數(shù)據(jù)操作指令都是"動(dòng)詞 + 賓語(yǔ)"的結(jié)構(gòu)夏块。比如疏咐,GET /articles這個(gè)命令,GET是動(dòng)詞脐供,/articles是賓語(yǔ)浑塞。
    動(dòng)詞通常就是五種 HTTP 方法,對(duì)應(yīng) CRUD 操作政己。
        GET:讀茸煤尽(Read)
        POST:新建(Create)
        PUT:更新(Update)
        PATCH:更新(Update),通常是部分更新
        DELETE:刪除(Delete)

根據(jù) HTTP 規(guī)范歇由,動(dòng)詞一律大寫卵牍。

  • 動(dòng)詞的覆蓋
    有些客戶端只能使用GET和POST這兩種方法。服務(wù)器必須接受POST模擬其他三個(gè)方法(PUT沦泌、PATCH糊昙、DELETE)。
    這時(shí)赦肃,客戶端發(fā)出的 HTTP 請(qǐng)求溅蛉,要加上X-HTTP-Method-Override屬性,告訴服務(wù)器應(yīng)該使用哪一個(gè)動(dòng)詞他宛,覆蓋POST方法船侧。
    POST /api/Person/4 HTTP/1.1  
    X-HTTP-Method-Override: PUT

上面代碼中,X-HTTP-Method-Override指定本次請(qǐng)求的方法是PUT厅各,而不是POST镜撩。

  • 賓語(yǔ)必須是名詞
    賓語(yǔ)就是 API 的 URL,是 HTTP 動(dòng)詞作用的對(duì)象队塘。它應(yīng)該是名詞袁梗,不能是動(dòng)詞。比如憔古,/articles這個(gè) URL 就是正確的遮怜,而下面的 URL 不是名詞,所以都是錯(cuò)誤的鸿市。
        /getAllCars
        /createNewCar
        /deleteAllRedCars
  • 復(fù)數(shù) URL
    既然 URL 是名詞锯梁,那么應(yīng)該使用復(fù)數(shù),還是單數(shù)焰情?
    這沒有統(tǒng)一的規(guī)定陌凳,但是常見的操作是讀取一個(gè)集合,比如GET /articles(讀取所有文章)内舟,這里明顯應(yīng)該是復(fù)數(shù)合敦。
    為了統(tǒng)一起見,建議都使用復(fù)數(shù) URL验游,比如GET /articles/2要好于GET /article/2充岛。
  • 避免多級(jí) URL
    常見的情況是保檐,資源需要多級(jí)分類,因此很容易寫出多級(jí)的 URL裸准,比如獲取某個(gè)作者的某一類文章展东。
    GET /authors/12/categories/2

RESTful的關(guān)鍵

RESTful的關(guān)鍵是定義可表示流程元素/資源的對(duì)象。在REST中炒俱,每一個(gè)對(duì)象都是通過(guò)URL來(lái)表示的盐肃,對(duì)象用戶負(fù)責(zé)將狀態(tài)信息打包進(jìn)每一條消息內(nèi),以便對(duì)象的處理總是無(wú)狀態(tài)的权悟。

4.狀態(tài)碼

4.1 狀態(tài)碼必須精確

客戶端的每一次請(qǐng)求砸王,服務(wù)器都必須給出回應(yīng)÷透螅回應(yīng)包括 HTTP 狀態(tài)碼和數(shù)據(jù)兩部分谦铃。
HTTP 狀態(tài)碼就是一個(gè)三位數(shù),分成五個(gè)類別榔昔。

  • 1xx:相關(guān)信息
  • 2xx:操作成功
  • 3xx:重定向
  • 4xx:客戶端錯(cuò)誤
  • 5xx:服務(wù)器錯(cuò)誤

每一種狀態(tài)碼都有標(biāo)準(zhǔn)的(或者約定的)解釋驹闰,客戶端只需查看狀態(tài)碼,就可以判斷出發(fā)生了什么情況撒会,所以服務(wù)器應(yīng)該返回盡可能精確的狀態(tài)碼嘹朗。
API 不需要1xx狀態(tài)碼,下面介紹其他四類狀態(tài)碼的精確含義诵肛。

4.2 2xx 狀態(tài)碼

200狀態(tài)碼表示操作成功屹培,但是不同的方法可以返回更精確的狀態(tài)碼。

  • GET: 200 OK
  • POST: 201 Created
  • PUT: 200 OK
  • PATCH: 200 OK
  • DELETE: 204 No Content

上面代碼中怔檩,POST返回201狀態(tài)碼褪秀,表示生成了新的資源;DELETE返回204狀態(tài)碼薛训,表示資源已經(jīng)不存在媒吗。
此外,202 Accepted狀態(tài)碼表示服務(wù)器已經(jīng)收到請(qǐng)求乙埃,但還未進(jìn)行處理闸英,會(huì)在未來(lái)再處理,通常用于異步操作膊爪。下面是一個(gè)例子。

HTTP/1.1 202 Accepted
{
 "task": {
    "href": "/api/company/job-management/jobs/2130040",
    "id": "2130040"
  }
}

4.3 3xx 狀態(tài)碼

API 用不到301狀態(tài)碼(永久重定向)和302狀態(tài)碼(暫時(shí)重定向嚎莉,307也是這個(gè)含義)米酬,因?yàn)樗鼈兛梢杂蓱?yīng)用級(jí)別返回,瀏覽器會(huì)直接跳轉(zhuǎn)趋箩,API 級(jí)別可以不考慮這兩種情況赃额。
API 用到的3xx狀態(tài)碼加派,主要是303 See Other,表示參考另一個(gè) URL跳芳。它與302307的含義一樣芍锦,也是"暫時(shí)重定向",區(qū)別在于302307用于GET請(qǐng)求飞盆,而303用于POST娄琉、PUTDELETE請(qǐng)求。收到303以后吓歇,瀏覽器不會(huì)自動(dòng)跳轉(zhuǎn)孽水,而會(huì)讓用戶自己決定下一步怎么辦。下面是一個(gè)例子城看。

HTTP/1.1 303 See Other
Location: /api/orders/12345

4.4 4xx 狀態(tài)碼

4xx狀態(tài)碼表示客戶端錯(cuò)誤女气,主要有下面幾種。
400 Bad Request:服務(wù)器不理解客戶端的請(qǐng)求测柠,未做任何處理炼鞠。
401 Unauthorized:用戶未提供身份驗(yàn)證憑據(jù),或者沒有通過(guò)身份驗(yàn)證轰胁。
403 Forbidden:用戶通過(guò)了身份驗(yàn)證谒主,但是不具有訪問(wèn)資源所需的權(quán)限。
404 Not Found:所請(qǐng)求的資源不存在软吐,或不可用瘩将。
405 Method Not Allowed:用戶已經(jīng)通過(guò)身份驗(yàn)證,但是所用的 HTTP 方法不在他的權(quán)限之內(nèi)凹耙。
410 Gone:所請(qǐng)求的資源已從這個(gè)地址轉(zhuǎn)移姿现,不再可用。
415 Unsupported Media Type:客戶端要求的返回格式不支持肖抱。比如备典,API 只能返回 JSON 格式,但是客戶端要求返回 XML 格式意述。
422 Unprocessable Entity :客戶端上傳的附件無(wú)法處理提佣,導(dǎo)致請(qǐng)求失敗。
429 Too Many Requests:客戶端的請(qǐng)求次數(shù)超過(guò)限額荤崇。

4.5 5xx 狀態(tài)碼

5xx狀態(tài)碼表示服務(wù)端錯(cuò)誤拌屏。一般來(lái)說(shuō),API 不會(huì)向用戶透露服務(wù)器的詳細(xì)信息术荤,所以只要兩個(gè)狀態(tài)碼就夠了倚喂。
500 Internal Server Error:客戶端請(qǐng)求有效,服務(wù)器處理時(shí)發(fā)生了意外瓣戚。
503 Service Unavailable:服務(wù)器無(wú)法處理請(qǐng)求端圈,一般用于網(wǎng)站維護(hù)狀態(tài)焦读。

5.服務(wù)器回應(yīng)

5.1 不要返回純本文

API 返回的數(shù)據(jù)格式,不應(yīng)該是純文本舱权,而應(yīng)該是一個(gè) JSON 對(duì)象矗晃,因?yàn)檫@樣才能返回標(biāo)準(zhǔn)的結(jié)構(gòu)化數(shù)據(jù)。所以宴倍,服務(wù)器回應(yīng)的 HTTP 頭的Content-Type屬性要設(shè)為application/json张症。
客戶端請(qǐng)求時(shí),也要明確告訴服務(wù)器啊楚,可以接受 JSON 格式吠冤,即請(qǐng)求的 HTTP 頭的ACCEPT屬性也要設(shè)成application/json。下面是一個(gè)例子恭理。

GET /orders/2 HTTP/1.1 
Accept: application/json 

5.2 發(fā)生錯(cuò)誤時(shí)拯辙,不要返回 200 狀態(tài)碼

有一種不恰當(dāng)?shù)淖龇ㄊ牵词拱l(fā)生錯(cuò)誤颜价,也返回200狀態(tài)碼涯保,把錯(cuò)誤信息放在數(shù)據(jù)體里面,就像下面這樣周伦。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "failure",
  "data": {
    "error": "Expected at least two items in list."
  }
}

上面代碼中夕春,解析數(shù)據(jù)體以后,才能得知操作失敗专挪。
這張做法實(shí)際上取消了狀態(tài)碼及志,這是完全不可取的。正確的做法是寨腔,狀態(tài)碼反映發(fā)生的錯(cuò)誤速侈,具體的錯(cuò)誤信息放在數(shù)據(jù)體里面返回。下面是一個(gè)例子迫卢。

HTTP/1.1 400 Bad Request
Content-Type: application/json
{
  "error": "Invalid payoad.",
  "detail": {
     "surname": "This field is required."
  }
}

5.3 提供鏈接

在回應(yīng)中倚搬,給出相關(guān)鏈接,便于下一步操作乾蛤。這樣的話每界,用戶只要記住一個(gè) URL,就可以發(fā)現(xiàn)其他的 URL家卖。這種方法叫做 HATEOAS眨层。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市上荡,隨后出現(xiàn)的幾起案子趴樱,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伊佃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沛善,警方通過(guò)查閱死者的電腦和手機(jī)航揉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)金刁,“玉大人帅涂,你說(shuō)我怎么就攤上這事∮嚷” “怎么了媳友?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)产捞。 經(jīng)常有香客問(wèn)我醇锚,道長(zhǎng),這世上最難降的妖魔是什么坯临? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任焊唬,我火速辦了婚禮,結(jié)果婚禮上看靠,老公的妹妹穿的比我還像新娘赶促。我一直安慰自己,他們只是感情好挟炬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布鸥滨。 她就那樣靜靜地躺著,像睡著了一般谤祖。 火紅的嫁衣襯著肌膚如雪婿滓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天泊脐,我揣著相機(jī)與錄音空幻,去河邊找鬼。 笑死容客,一個(gè)胖子當(dāng)著我的面吹牛秕铛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缩挑,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼但两,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了供置?” 一聲冷哼從身側(cè)響起谨湘,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后紧阔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坊罢,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年擅耽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了活孩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乖仇,死狀恐怖憾儒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乃沙,我是刑警寧澤起趾,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站警儒,受9級(jí)特大地震影響训裆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜀铲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一缭保、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝙茶,春花似錦艺骂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蹄衷,卻和暖如春忧额,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愧口。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工睦番, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耍属。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓托嚣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厚骗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子示启,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容