RESTful API 設(shè)計(jì)指南 —— 最佳實(shí)踐

編譯自:RESTful API Designing guidelines?—?The best practices

譯者:開(kāi)源中國(guó) - ismdeep, Tocy, 無(wú)若, butta, 昌偉兄, osbertngok

Facebook、谷歌、Github、Netflix 和幾個(gè)其他的科技巨頭已經(jīng)允許開(kāi)發(fā)者和其產(chǎn)品通過(guò) API 調(diào)用他們的數(shù)據(jù),并為他們提供平臺(tái)。即使你不是寫(xiě) API 的專(zhuān)業(yè)人士,擁有精美的 API 也對(duì)你的應(yīng)用程序有好處。

關(guān)于設(shè)計(jì) API 的最好方法,網(wǎng)絡(luò)上有較長(zhǎng)一段時(shí)間的爭(zhēng)論,但官方也沒(méi)有對(duì)此給出解釋。

API 是一個(gè)接口,通過(guò)它許多開(kāi)發(fā)者可與數(shù)據(jù)交互。 設(shè)計(jì)優(yōu)良的 API 使用起來(lái)很方便,并給開(kāi)發(fā)者的工作帶來(lái)便利。 API 是開(kāi)發(fā)者的 GUI,如果它設(shè)計(jì)不合理,開(kāi)發(fā)者會(huì)將它替換。所以,開(kāi)發(fā)者的經(jīng)驗(yàn)是衡量 API 質(zhì)量的最重要的指標(biāo)。

"API就像一個(gè)在舞臺(tái)上表演的藝術(shù)家,其用戶(hù)就是其觀眾"

1) 術(shù)語(yǔ)

以下是與 REST API 相關(guān)的重要術(shù)語(yǔ):

資源(Resource) 是一個(gè)對(duì)象或?qū)δ澄锏谋硎尽K幸恍┫嚓P(guān)聯(lián)的數(shù)據(jù),并有一組方法進(jìn)行操作。 例如:動(dòng)物,學(xué)校和員工是資源。這些資源都有著刪除,添加,更新操作。

集合(Collection)是一系列資源,例如:公司集合是很多公司的集合。

URL(統(tǒng)一資源定位符)是一種路徑,可以通過(guò)它定位資源并且也可以對(duì)它執(zhí)行一些動(dòng)作。

2) API 端點(diǎn)(路徑)

為了更好理解,我們給公司寫(xiě) API,這些公司都有一些員工。/getAllEmployees 是對(duì)員工列表進(jìn)行回應(yīng)的 API。公司其他 API 大致如下:

/addNewEmployee

/updateEmployee

/deleteEmployee

/deleteAllEmployees

/promoteEmployee

/promoteAllEmployees

并且將有大量的和這些操作不同的 API 端點(diǎn),它們包含大量冗余的行為。因此,當(dāng) API 數(shù)量增加時(shí),這些 API 端點(diǎn)將很難維護(hù)。

哪里不對(duì)?

每個(gè) URL 代表一種資源(Resource),所以 URL 中只能有名詞,不能有動(dòng)詞。 API 路徑 /addNewEmployee 包含了操作 addNew 和資源名稱(chēng)?Employee。

那么怎樣算是正確的方式?

/companies 是一個(gè)很好的不包含操作的例子。但是問(wèn)題來(lái)了,我們?cè)撛鯓痈嬖V服務(wù)器我們要進(jìn)行的操作呢?新增,刪除,還是更新?

這時(shí)HTTP 方法(GET,POST,DELETE,PUT)(也稱(chēng)為動(dòng)詞)就可以起到作用了。

資源在 API 端點(diǎn)中應(yīng)該總是復(fù)數(shù),如果我們想訪(fǎng)問(wèn)資源的一個(gè)實(shí)例,我們可以傳遞 URL 中的 id。

方法 GET 路徑 /companies 是獲取所有公司的列表。

方法 GET?路徑 /companies/34 是獲取公司34的詳細(xì)信息。

方法 DELETE?路徑 /companies/34 是刪除公司34。

在其他的一些使用案例中,如果我們有一些資源在某個(gè)資源之下,例如,一個(gè)公司的員工,那么在這樣的例子中 API 的 endpoint(端點(diǎn)) 就應(yīng)該是這樣的:

GET /companies/3/employees 可以取得編號(hào)為3的公司的員工列表

GET /companies/3/employees/45?可以取得編號(hào)為3的公司的45號(hào)員工的細(xì)節(jié)信息

DELETE /companies/3/employees/45 可以刪除編號(hào)為3的公司的45號(hào)員工

POST /companies 可以創(chuàng)建一個(gè)新公司并返回新創(chuàng)建公司的細(xì)節(jié)信息

現(xiàn)在這樣,API 是不是更嚴(yán)謹(jǐn)和一致了呢?

結(jié)論:路徑應(yīng)該包含資源的復(fù)數(shù)形式,HTTP 方法應(yīng)該定義成各種行為在資源上執(zhí)行。

3) HTTP 方法 (動(dòng)詞)

HTTP 定義了幾組方法,這些方法給出了對(duì)資源要執(zhí)行的操作類(lèi)型。

URL 是一個(gè)句子,其中資源是名詞,HTTP 方法是動(dòng)詞。

主要的HTTP方法如下:

GET 方法從資源請(qǐng)求數(shù)據(jù),不產(chǎn)生多余結(jié)果。

例如: /companies/3/employees 會(huì)返回公司3的所有雇員列表。

POST 方法請(qǐng)求服務(wù)器在數(shù)據(jù)庫(kù)中創(chuàng)建資源,這主要用于提交 Web 表單時(shí)。

例如: /companies/3/employees 創(chuàng)建一個(gè)公司3的新雇員。

POST 是非冪等的,這意味著多個(gè)請(qǐng)求將會(huì)有不同的效果。

PUT 方法請(qǐng)求服務(wù)器更新資源或創(chuàng)建資源(如果不存在的話(huà))。

例如: /companies/3/employees/john 將請(qǐng)求服務(wù)器在公司3的雇員集合中更新或在不存在的情況下創(chuàng)建關(guān)于 john 的資源。

PUT 是冪等的,這意味著多次請(qǐng)求具有相同的效果。

DELETE 方法將請(qǐng)求的資源或?qū)嵗龔臄?shù)據(jù)庫(kù)中刪除。

例如: /companies/3/employees/john/ 將請(qǐng)求服務(wù)器從公司3的雇員集中刪除 john 資源。

HTTP 中還有很多其他方法,我們將在另一篇文章中討論。

4) HTTP 響應(yīng)狀態(tài)碼

當(dāng)客戶(hù)端通過(guò) API 向服務(wù)器發(fā)起請(qǐng)求時(shí),無(wú)論請(qǐng)求是失敗的、通過(guò)的還是錯(cuò)誤的,客戶(hù)端應(yīng)該獲得反饋。HTTP 狀態(tài)碼是一堆標(biāo)準(zhǔn)化的數(shù)值碼,在不同的情況下具有不同的解釋。服務(wù)器應(yīng)始終返回正確的狀態(tài)碼。

以下是 HTTP 狀態(tài)碼的主要分類(lèi):

2xx (成功類(lèi)別)

這些狀態(tài)代碼表示請(qǐng)求的操作已被服務(wù)器接收到并成功處理。

200 Ok:標(biāo)準(zhǔn)的 HTTP 響應(yīng),表示 GET、PUT 或 POST 的處理成功。

201 Created:在創(chuàng)建新實(shí)例時(shí),應(yīng)返回此狀態(tài)代碼。例如,使用 POST 方法創(chuàng)建一個(gè)新的實(shí)例,應(yīng)該始終返回 201 狀態(tài)碼。

204 內(nèi)容不存在:表示請(qǐng)求已被成功處理,但并未返回任何內(nèi)容。

DELETE算是其中一個(gè)很好的例子。

API DELETE /companies/43/employees/2?將刪除員工 2,作為響應(yīng),我們不需要在該 API 的響應(yīng)正文中的任何數(shù)據(jù),因?yàn)槲覀兠鞔_地要求系統(tǒng)將其刪除。如果有任何錯(cuò)誤發(fā)生,例如,如果員工 2 在數(shù)據(jù)庫(kù)中不存在,那么響應(yīng)碼將不是 2xx 對(duì)應(yīng)的成功類(lèi)別,而是 4xx 客戶(hù)端錯(cuò)誤類(lèi)別。

3xx (重定向類(lèi)別)

304 未修改:表示客戶(hù)端的響應(yīng)已經(jīng)在其緩存中。 因此,不需要再次傳送相同的數(shù)據(jù)。

4xx (客戶(hù)端錯(cuò)誤類(lèi)別)

這些狀態(tài)代碼表示客戶(hù)端發(fā)起了錯(cuò)誤的請(qǐng)求。

400 錯(cuò)誤請(qǐng)求:表示客戶(hù)端的請(qǐng)求沒(méi)有被處理,因?yàn)榉?wù)器不能理解客戶(hù)端請(qǐng)求的是什么。

401 未授權(quán):表示客戶(hù)端不被允許訪(fǎng)問(wèn)該資源,需要使用指定憑證重新請(qǐng)求。

403 禁止訪(fǎng)問(wèn):表示請(qǐng)求是有效的并且客戶(hù)端已通過(guò)身份驗(yàn)證,但客戶(hù)端不被允許以任何理由訪(fǎng)問(wèn)對(duì)應(yīng)頁(yè)面或資源。 例如有時(shí)授權(quán)的客戶(hù)端不被允許訪(fǎng)問(wèn)服務(wù)器上的目錄。

404 未找到:表示所請(qǐng)求的資源現(xiàn)在不可用。

410 資源不可用:表示所請(qǐng)求的資源后續(xù)不再可用,該資源已被移動(dòng)。

5xx(服務(wù)器錯(cuò)誤類(lèi)別)

500是服務(wù)器內(nèi)部錯(cuò)誤,表示請(qǐng)求已經(jīng)被接收到了,但服務(wù)器被要求處理某些未預(yù)設(shè)的請(qǐng)求而完全混亂。

503服務(wù)不可用表示服務(wù)器已關(guān)閉或無(wú)法接收和處理請(qǐng)求。大多數(shù)情況是服務(wù)器正在進(jìn)行維護(hù)。

5) 字段套管約定

您可以遵循任何套管約定,但要確保其在應(yīng)用程序中一致。如果請(qǐng)求主體或響應(yīng)類(lèi)型是JSON,那么請(qǐng)按照camelCase(駝峰命名法)來(lái)保持一致。

6) 搜索、排序、過(guò)濾和分頁(yè)

這些行為都只是針對(duì)一個(gè)數(shù)據(jù)集進(jìn)行的查詢(xún)。由于還沒(méi)有一套新的 API 來(lái)處理這些行為。因此,我們需要向 GET 方法的 API 附加查詢(xún)參數(shù)。

我們來(lái)理解幾個(gè)例子看它們是如何實(shí)現(xiàn)這些行為的。

排序(sorting),客戶(hù)端想要獲得排序后的公司列表,GET /companies 端點(diǎn)應(yīng)當(dāng)接受多個(gè)查詢(xún)排序參數(shù)。

例如,GET /companies?sort=rank_asc 將根據(jù)等級(jí)以升序的方式對(duì)公司進(jìn)行排序。

過(guò)濾(Filtering),用來(lái)過(guò)濾數(shù)據(jù)集,我們可以通過(guò)查詢(xún)參數(shù)傳遞不同的選項(xiàng)。

例如,GET /companies?category=banking&location=india 將根據(jù)公司類(lèi)別為銀行以及所處位置為印度來(lái)過(guò)濾公司的列表數(shù)據(jù)。

搜索(Searching),當(dāng)需要在公司列表中搜索公司名稱(chēng)時(shí),API 端點(diǎn)應(yīng)當(dāng)是 GET /companies?search=Digital Mckinsey。

分頁(yè)(Pagination),當(dāng)數(shù)據(jù)集太大時(shí),我們將數(shù)據(jù)集分成更小的塊,這樣有助于提高性能,并且更易于處理響應(yīng)。 例如,GET /companies?page=23 表示獲取第 23 頁(yè)的公司列表。

如果在 GET 方法中附加了很多查詢(xún)參數(shù),會(huì)造成 URI 太長(zhǎng),服務(wù)器可能會(huì)響應(yīng) 414 的 HTTP 狀態(tài),表示這個(gè) URI 太長(zhǎng),在這種情況下,我們也可以將參數(shù)傳遞給 POST 方法的請(qǐng)求體中。

7) 版本控制

當(dāng)你的 API 被開(kāi)始被廣泛使用后,突然升級(jí)API會(huì)打破現(xiàn)有的產(chǎn)品、服務(wù)。

這里有個(gè)一個(gè)很好的例子,它的路徑中有API的版本號(hào)。如果有任何重大的中斷更新,我們可以將新的API集命名為v2或v1.x.x

這些指南是根據(jù)我的開(kāi)發(fā)經(jīng)驗(yàn)編寫(xiě)的。我很想知道你對(duì)上述幾點(diǎn)的看法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評(píng)論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,744評(píng)論 3 421
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,879評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,181評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,935評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,325評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評(píng)論 3 443
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,534評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,084評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,892評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,067評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,322評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,735評(píng)論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,990評(píng)論 1 289
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,800評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,084評(píng)論 2 375

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