[译] RESTful API 设计最佳实践
https://juejin.im/entry/6844903503953920007
?
?
[譯] RESTful API 設(shè)計(jì)最佳實(shí)踐
閱讀 8779
收藏 0
2017-10-16
原文鏈接:?segmentfault.com
原文:RESTful API Design. Best Practices in a Nutshell.
作者:Philipp Hauer
項(xiàng)目資源的URL應(yīng)該如何設(shè)計(jì)?用名詞復(fù)數(shù)還是用名詞單數(shù)?一個(gè)資源需要多少個(gè)URL?用哪種HTTP方法來(lái)創(chuàng)建一個(gè)新的資源?可選參數(shù)應(yīng)該放在哪里?那些不涉及資源操作的URL呢?實(shí)現(xiàn)分頁(yè)和版本控制的最好方法是什么?因?yàn)橛刑嗟囊蓡?wèn),設(shè)計(jì)RESTful API變得很棘手。在這篇文章中,我們來(lái)看一下RESTful API設(shè)計(jì),并給出一個(gè)最佳實(shí)踐方案。
每個(gè)資源使用兩個(gè)URL
資源集合用一個(gè)URL,具體某個(gè)資源用一個(gè)URL:
/employees #資源集合的URL /employees/56 #具體某個(gè)資源的URL用名詞代替動(dòng)詞表示資源
這讓你的API更簡(jiǎn)潔,URL數(shù)目更少。不要這么設(shè)計(jì):
/getAllEmployees /getAllExternalEmployees /createEmployee /updateEmployee更好的設(shè)計(jì):
GET /employees GET /employees?state=external POST /employees PUT /employees/56用HTTP方法操作資源
使用URL指定你要用的資源。使用HTTP方法來(lái)指定怎么處理這個(gè)資源。使用四種HTTP方法POST,GET,PUT,DELETE可以提供CRUD功能(創(chuàng)建,獲取,更新,刪除)。
- 獲取:使用GET方法獲取資源。GET請(qǐng)求從不改變資源的狀態(tài)。無(wú)副作用。GET方法是冪等的。GET方法具有只讀的含義。因此,你可以完美的使用緩存。
- 創(chuàng)建:使用POST創(chuàng)建新的資源。
- 更新:使用PUT更新現(xiàn)有資源。
- 刪除:使用DELETE刪除現(xiàn)有資源。
2個(gè)URL乘以4個(gè)HTTP方法就是一組很好的功能。看看這個(gè)表格:
| /employees | 創(chuàng)建一個(gè)新員工 | 列出所有員工 | 批量更新員工信息 | 刪除所有員工 |
| /employees/56 | (錯(cuò)誤) | 獲取56號(hào)員工的信息 | 更新56號(hào)員工的信息 | 刪除56號(hào)員工 |
對(duì)資源集合的URL使用POST方法,創(chuàng)建新資源
創(chuàng)建一個(gè)新資源的時(shí),客戶端與服務(wù)器是怎么交互的呢?
在資源集合URL上使用POST來(lái)創(chuàng)建新的資源過(guò)程:
對(duì)具體資源的URL使用PUT方法,來(lái)更新資源
使用PUT更新已有資源:
推薦用復(fù)數(shù)名詞
推薦:
/employees /employees/21不推薦:
/employee /employee/21事實(shí)上,這是個(gè)人愛(ài)好問(wèn)題,但復(fù)數(shù)形式更為常見(jiàn)。此外,在資源集合URL上用GET方法,它更直觀,特別是GET /employees?state=external、POST /employees、PUT /employees/56。但最重要的是:避免復(fù)數(shù)和單數(shù)名詞混合使用,這顯得非常混亂且容易出錯(cuò)。
對(duì)可選的、復(fù)雜的參數(shù),使用查詢字符串(?)。
不推薦做法:
GET /employees GET /externalEmployees GET /internalEmployees GET /internalAndSeniorEmployees為了讓你的URL更小、更簡(jiǎn)潔。為資源設(shè)置一個(gè)基本URL,將可選的、復(fù)雜的參數(shù)用查詢字符串表示。
GET /employees?state=internal&maturity=senior使用HTTP狀態(tài)碼
RESTful Web服務(wù)應(yīng)使用合適的HTTP狀態(tài)碼來(lái)響應(yīng)客戶端請(qǐng)求
- 2xx - 成功 - 一切都很好
- 4xx - 客戶端錯(cuò)誤 - 如果客戶端發(fā)生錯(cuò)誤(例如客戶端發(fā)送無(wú)效請(qǐng)求或未被授權(quán))
- 5xx – 服務(wù)器錯(cuò)誤 - 如果服務(wù)器發(fā)生錯(cuò)誤(例如,嘗試處理請(qǐng)求時(shí)出錯(cuò))
參考維基百科上的HTTP狀態(tài)代碼。但是,其中的大部分HTTP狀態(tài)碼都不會(huì)被用到,只會(huì)用其中的一小部分。通常會(huì)用到一下幾個(gè):
| 200 成功 | 301 永久重定向 | 400 錯(cuò)誤請(qǐng)求 | 500 內(nèi)部服務(wù)器錯(cuò)誤 |
| 201 創(chuàng)建 | 304 資源未修改 | 401未授權(quán) | ? |
| ? | ? | 403 禁止 | ? |
| ? | ? | 404 未找到 | ? |
返回有用的錯(cuò)誤提示
除了合適的狀態(tài)碼之外,還應(yīng)該在HTTP響應(yīng)正文中提供有用的錯(cuò)誤提示和詳細(xì)的描述。這是一個(gè)例子。請(qǐng)求:
GET /employees?state=super響應(yīng):
// 400 Bad Request {"message": "You submitted an invalid state. Valid state values are 'internal' or 'external'","errorCode": 352,"additionalInformation" : "http://www.domain.com/rest/errorcode/352" }使用小駝峰命名法
使用小駝峰命名法作為屬性標(biāo)識(shí)符。
{?"yearOfBirth":?1982?}不要使用下劃線(year_of_birth)或大駝峰命名法(YearOfBirth)。通常,RESTful Web服務(wù)將被JavaScript編寫的客戶端使用。客戶端會(huì)將JSON響應(yīng)轉(zhuǎn)換為JavaScript對(duì)象(通過(guò)調(diào)用var person = JSON.parse(response)),然后調(diào)用其屬性。因此,最好遵循JavaScript代碼通用規(guī)范。
對(duì)比:
在URL中強(qiáng)制加入版本號(hào)
從始至終,都使用版本號(hào)發(fā)布您的RESTful API。將版本號(hào)放在URL中以是必需的。如果您有不兼容和破壞性的更改,版本號(hào)將讓你能更容易的發(fā)布API。發(fā)布新API時(shí),只需在增加版本號(hào)中的數(shù)字。這樣的話,客戶端可以自如的遷移到新API,不會(huì)因調(diào)用完全不同的新API而陷入困境。 使用直觀的 “v” 前綴來(lái)表示后面的數(shù)字是版本號(hào)。
/v1/employees你不需要使用次級(jí)版本號(hào)(“v1.2”),因?yàn)槟悴粦?yīng)該頻繁的去發(fā)布API版本。
提供分頁(yè)信息
一次性返回?cái)?shù)據(jù)庫(kù)所有資源不是一個(gè)好主意。因此,需要提供分頁(yè)機(jī)制。通常使用數(shù)據(jù)庫(kù)中眾所周知的參數(shù)offset和limit。
/employees?offset=30&limit=15?#返回30?到?45的員工如果客戶端沒(méi)有傳這些參數(shù),則應(yīng)使用默認(rèn)值。通常默認(rèn)值是offset = 0和limit = 10。如果數(shù)據(jù)庫(kù)檢索很慢,應(yīng)當(dāng)減小limit值。
/employees #返回0?到?10的員工此外,如果您使用分頁(yè),客戶端需要知道資源總數(shù)。例:請(qǐng)求:
GET?/employees響應(yīng):
{"offset": 0,"limit": 10,"total": 3465,"employees": [//...] }非資源請(qǐng)求用動(dòng)詞
有時(shí)API調(diào)用并不涉及資源(如計(jì)算,翻譯或轉(zhuǎn)換)。例:
GET /translate?from=de_DE&to=en_US&text=Hallo GET /calculate?para2=23¶2=432在這種情況下,API響應(yīng)不會(huì)返回任何資源。而是執(zhí)行一個(gè)操作并將結(jié)果返回給客戶端。因此,您應(yīng)該在URL中使用動(dòng)詞而不是名詞,來(lái)清楚的區(qū)分資源請(qǐng)求和非資源請(qǐng)求。
考慮特定資源搜索和跨資源搜索
提供對(duì)特定資源的搜索很容易。只需使用相應(yīng)的資源集合URL,并將搜索字符串附加到查詢參數(shù)中即可。
GET /employees?query=Paul如果要對(duì)所有資源提供全局搜索,則需要用其他方法。前文提到,對(duì)于非資源請(qǐng)求URL,使用動(dòng)詞而不是名詞。因此,您的搜索網(wǎng)址可能如下所示:
GET /search?query=Paul?//返回 employees, customers, suppliers 等等.在響應(yīng)參數(shù)中添加瀏覽其它API的鏈接
理想情況下,不會(huì)讓客戶端自己構(gòu)造使用REST API的URL。讓我們思考一個(gè)例子。
客戶端想要訪問(wèn)員工的薪酬表。為此,他必須知道他可以通過(guò)在員工URL(例如/employees/21/salaryStatements)中附加字符串“salaryStatements”來(lái)訪問(wèn)薪酬表。這個(gè)字符串連接很容易出錯(cuò),且難以維護(hù)。如果你更改了訪問(wèn)薪水表的REST API的方式(例如變成了/employees/21/salary-statement或/employees/21/paySlips),所有客戶端都將中斷。
更好的方案是在響應(yīng)參數(shù)中添加一個(gè)links字段,讓客戶端可以自動(dòng)變更。
請(qǐng)求:
響應(yīng):
//...{"id":1,"name":"Paul","links": [{"rel": "salary","href": "/employees/1/salaryStatements"}]}, //...如果客戶端完全依靠links中的字段獲得薪資表,你更改了API,客戶端將始終獲得一個(gè)有效的URL(只要你更改了link字段,請(qǐng)求的URL會(huì)自動(dòng)更改),不會(huì)中斷。另一個(gè)好處是,你的API變得可以自我描述,需要寫的文檔更少。
在分頁(yè)時(shí),您還可以添加獲取下一頁(yè)或上一頁(yè)的鏈接示例。只需提供適當(dāng)?shù)钠坪拖拗频逆溄邮纠?/p>
GET /employees?offset=20&limit=10
{"offset": 20,"limit": 10,"total": 3465,"employees": [//...],"links": [{"rel": "nextPage","href": "/employees?offset=30&limit=10"},{"rel": "previousPage","href": "/employees?offset=10&limit=10"}]
}
相關(guān)閱讀:
- 作者寫的一篇關(guān)于在Java中測(cè)試RESTful服務(wù)的最佳實(shí)踐的文章。
- 作者強(qiáng)烈推薦一本書B(niǎo)rain Mulloy’s nice paper,作為這篇文章的基礎(chǔ)。
- API
- 設(shè)計(jì)
- 服務(wù)器
- 后端
?
hellostory
實(shí)際開(kāi)發(fā)中,對(duì)外暴露簡(jiǎn)單接口倒還可以,如果系統(tǒng)所有功能都按RESTFul開(kāi)發(fā),簡(jiǎn)直找死,或許是本人能力不夠吧。比如登錄、注銷、上傳文件、審批、反審批、更改單據(jù)狀態(tài)、修改訂單數(shù)量、保存訂單排序、投料、暫停、恢復(fù)…… 各種想到?jīng)]想到的功能,你怎么分類
2年前
1
回復(fù)
雪中魚01?
后端開(kāi)發(fā)
是啊,我也在想,不知道如果有些復(fù)雜邏輯處理的接口要怎么制定api,但是好像好多大公司在用restful api,像twitter、instagramer,不知道他們?cè)趺刺幚淼?#xff5e;
1年前
回復(fù)
leto40438?
web 前端 @ 字節(jié)跳動(dòng)
回復(fù)?
雪中魚01
:?這就體現(xiàn)出經(jīng)驗(yàn)的作用了吧,不只是熟悉規(guī)則就行,還需要大量的實(shí)際開(kāi)發(fā)經(jīng)驗(yàn)1年前
回復(fù)
雪中魚01?
后端開(kāi)發(fā)
回復(fù)?
leto40438
:?這是句看似有道理的廢話,技術(shù)的迭代不就是要減少靠經(jīng)驗(yàn)的操作嗎?弓箭要想射的準(zhǔn)就得靠經(jīng)過(guò)良好訓(xùn)練的弓箭手,手槍的發(fā)明不就是讓人人都可以進(jìn)行設(shè)計(jì)嗎?如果一個(gè)發(fā)明的代價(jià)是增加了另一個(gè)需要大量經(jīng)驗(yàn)的過(guò)程,那這個(gè)發(fā)明就是錯(cuò)的,無(wú)用的1年前
1
回復(fù)
ikeguang
數(shù)據(jù)開(kāi)發(fā)
回復(fù)?
雪中魚01
:?同意1年前
回復(fù)
葉嘉祺同學(xué)
可以參考 google api convention:cloud.google.com/apis/design。規(guī)范是為了提高效率,同時(shí)方便大家之間對(duì)接
2月前
回復(fù)
七者
JAVA后端
贊!剛好需要了解restful
2年前
回復(fù)
下載掘金客戶端
一個(gè)幫助開(kāi)發(fā)者成長(zhǎng)的社區(qū)
相關(guān)文章
一文快速入門分庫(kù)分表(送給不知該學(xué)點(diǎn)啥的你)
?38
?
?5
談?wù)勄昂蠖朔蛛x及認(rèn)證選擇
?22
?
?0
手寫一個(gè)抖音視頻去水印工具,千萬(wàn)別剛一個(gè)程序員
?123
?
?79
還在手寫任務(wù)調(diào)度代碼?試試這款可視化分布式調(diào)度框架!
?15
?
?2
探討技術(shù)團(tuán)隊(duì)文化和 996 之間的關(guān)系
?11
?
?21
分享
| 掘金瀏覽器插件 - 打
總結(jié)
以上是生活随笔為你收集整理的[译] RESTful API 设计最佳实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果电脑系统可以玩lol吗(苹果电脑系统
- 下一篇: centos安装docker显示 No