前言
最近我司要制定開發(fā)規(guī)范斩郎。在討論接口返回的時(shí)候脑融,后端的同事詢問我們前端,錯(cuò)誤信息的返回缩宜,前端有什么意見肘迎?
所以做了一些調(diào)研給到后端的同事做參考。
錯(cuò)誤信息返回
在使用API
時(shí)無可避免地會(huì)因?yàn)楦鞣N情況而導(dǎo)致接口返回錯(cuò)誤的信息锻煌。比如指定的query
參數(shù)錯(cuò)誤妓布,又或者method
不支持等,這些情況都會(huì)返回相關(guān)的錯(cuò)誤信息宋梧。另外服務(wù)器不穩(wěn)定或者停止運(yùn)行了匣沼,也必須將錯(cuò)誤信息返回。
顯然捂龄,當(dāng)錯(cuò)誤發(fā)生的時(shí)候释涛,只是籠統(tǒng)地返回“發(fā)生了錯(cuò)誤”是不行的。如果前端不了解發(fā)生了什么錯(cuò)誤跺讯,也就不知道該怎么去調(diào)試枢贿,怎么去修復(fù)這個(gè)bug
。所以說刀脏,必須向前端返回盡可能多的信息局荚,以便前端找到出錯(cuò)的地方解決問題。
通過HTTP狀態(tài)碼表示出錯(cuò)信息
首先必須選擇合適的HTTP
狀態(tài)碼愈污,之前我司的后端API
沒有遵循這個(gè)規(guī)則耀态。例如API
無論如何訪問,都會(huì)返回200
狀態(tài)碼暂雹,只在返回消息體中的描述是否發(fā)生錯(cuò)誤首装。
HTTP/1.1 200 OK
Content-Type: application/json
{
"error": {
"code": 2002,
"message": "Invalid parameter"
}
}
雖然這么處理前端也能理解API
的錯(cuò)誤信息,但由于HTTP
協(xié)議已經(jīng)完整地定義了各個(gè)狀態(tài)碼所表示的含義杭跪,所以返回恰當(dāng)?shù)臓顟B(tài)碼才能提高前端正確識(shí)別錯(cuò)誤的可能性仙逻。
如果出錯(cuò)了驰吓,仍然返回200
狀態(tài)碼,有可能導(dǎo)致前端的處理發(fā)生混亂系奉,這種情況要一定要禁止檬贰。特別是通用的API
,基本上都是先看狀態(tài)碼再?zèng)Q定下一步的處理缺亮,如果沒有返回正確的狀態(tài)碼翁涤,就會(huì)導(dǎo)致前端無法執(zhí)行適當(dāng)?shù)姆椒ㄈヌ幚恚瑥亩l(fā)各種不必要的問題萌踱。而且這種做法沒有盡可能地運(yùn)用HTTP
協(xié)議葵礼,也給前端編寫錯(cuò)誤處理增加了難度。
- 狀態(tài)碼分類
狀態(tài)碼 | 含義 |
---|---|
1xx | 消息 |
2xx | 成功 |
3xx | 重定向 |
4xx | 前端原因引起的錯(cuò)誤 |
5xx | 服務(wù)器原因引起的錯(cuò)誤 |
下面主要來了解一下4xx
和5xx
的錯(cuò)誤碼:
4xx
-前端發(fā)生了錯(cuò)誤
4xx
的狀態(tài)碼主要是用于描述因前端請求的問題而引發(fā)的錯(cuò)誤并鸵,也就是說服務(wù)器端不存在出錯(cuò)問題鸳粉,但服務(wù)器端無法理解前端的請求,或者能理解但無法處理的請求能真。這一類的錯(cuò)誤赁严,統(tǒng)一使用4xx
錯(cuò)誤碼扰柠。
狀態(tài)碼 | 名稱 | 說明 |
---|---|---|
400 | Bad Request | 表示其他錯(cuò)誤粉铐,就是4xx都無法描述的前端發(fā)生的錯(cuò)誤 |
401 | Authentication | 表示認(rèn)證類型的錯(cuò)誤 |
403 | Authorization | 表示授權(quán)的錯(cuò)誤(認(rèn)證和授權(quán)的區(qū)別在于:認(rèn)證表示“識(shí)別前來訪問的是誰”,而授權(quán)則是“賦予特定用戶執(zhí)行特定操作的權(quán)限”) |
404 | Not Found | 表示訪問的數(shù)據(jù)不存在 |
405 | Method Not Allowd | 表示可以訪問接口卤档,但是使用的HTTP方法不允許 |
406 | Not Acceptable | 表示API不支持前端指定的數(shù)據(jù)格式 |
408 | Request Timeout | 表示前端發(fā)送的請求到服務(wù)器所需的時(shí)間太長 |
409 | Confilct | 表示資源發(fā)生了沖突蝙泼,比如使用已被注冊郵箱地址注冊時(shí),就引起沖突 |
410 | Gone | 表示訪問的資源不存在劝枣。不單表示資源不存在汤踏,還進(jìn)一步告知該資源該資源曾經(jīng)存在但目前已消失 |
413 | Request Entity Too Large | 表示請求的消息體過長而引發(fā)的錯(cuò)誤 |
414 | Request-URI Too Large | 表示請求的首部過長而引發(fā)的錯(cuò)誤 |
415 | Unsupported Media Type | 表示服務(wù)器端不支持客戶端請求首部Content-Type里指定的數(shù)據(jù)格式 |
416 | Range Not Satisfiable | 表示無法提供Range請求中的指定的那段包體 |
417 | Expectation Failed | 表示對于Expect請求頭部期待的情況無法滿足時(shí)的響應(yīng)碼 |
421 | Misdirected Request | 表示服務(wù)器認(rèn)為這個(gè)請求不該發(fā)給它,因?yàn)樗鼪]能力處理 |
426 | Upgrade Required | 表示服務(wù)器拒絕基于當(dāng)前HTTP協(xié)議提供服務(wù)舔腾,通過Upgrade頭部告知客戶端必須升級協(xié)議才能繼續(xù)處理 |
428 | Precondition Required | 表示用戶請求中缺失了條件類頭部溪胶,例如If-Match |
429 | Too Many Requests | 表示客戶端發(fā)送請求的速率過快 |
431 | Request Header Fields Too Large | 表示請求的HEADER頭部大小超出限制 |
451 | Unavailable For Legal Reasons | 表示由于法律原因不可訪問 |
5xx
-服務(wù)器端發(fā)生錯(cuò)誤
5xx
狀態(tài)碼表示錯(cuò)誤由服務(wù)器端的問題引發(fā)的。
狀態(tài)碼 | 名稱 | 說明 |
---|---|---|
500 | Internal Server Error | 表示服務(wù)器內(nèi)部錯(cuò)誤稳诚,且不屬于以下錯(cuò)誤類型 |
501 | Not Implemented | 表示服務(wù)器不支持實(shí)現(xiàn)請求所需要的功能 |
502 | Bad Gateway | 代理服務(wù)器無法獲取到合法資源 |
503 | Service Unavailable | 服務(wù)器資源尚未準(zhǔn)備好處理當(dāng)前請求 |
504 | Gateway Timeout | 表示代理服務(wù)器無法及時(shí)的從上游獲得響應(yīng) |
505 | HTTP Verson Not Supported | 表示請求使用的HTTP協(xié)議版本不支持 |
507 | Insufficient Storage | 表示服務(wù)器沒有足夠的空間處理請求 |
508 | Loop Detected | 表示訪問資源時(shí)檢測到循環(huán) |
511 | Network Authentication Required | 表示代理服務(wù)器發(fā)現(xiàn)客戶端需要進(jìn)行身份驗(yàn)證才能獲得網(wǎng)絡(luò)訪問權(quán)限 |
向前端返回詳細(xì)的錯(cuò)誤信息
當(dāng)錯(cuò)誤發(fā)生時(shí)哗脖,除了需要返回相應(yīng)的狀態(tài)碼之外,還需要返回詳情的錯(cuò)誤信息扳还。因?yàn)闋顟B(tài)碼只是通用的描述錯(cuò)誤的類別才避,一般無法表示實(shí)際發(fā)生的具體錯(cuò)誤信息。
比如說400
狀態(tài)碼氨距,只是知道前端請求發(fā)生了錯(cuò)誤桑逝,至于如何去修改,僅憑這個(gè)是沒有辦法找到bug
的俏让。
通常來說:返回錯(cuò)誤信息的方法有兩種:
- 將信息放入
HTTP
響應(yīng)頭 - 將信息通過
HTTP
響應(yīng)體返回
1楞遏、通過自定義頭部茬暇,將詳細(xì)的錯(cuò)誤信息放入響應(yīng)頭中
X-ERROR-CODE: 2020
X-ERROR-MESSAGE: Bad authentication token
X-ERROR-INFO: http://api.example.com/v1/authentication
2、將錯(cuò)誤信息放入響應(yīng)體中
{
"error": {
"code": 2020,
"message": "Bad authentication token",
"info": "http://api.example.com/v1/authentication"
}
}
從前端的角度來考慮寡喝,通過響應(yīng)體返回會(huì)更加容易處理而钞。
這里的錯(cuò)誤代碼的命名方式,按照后端自己的要求編寫即可拘荡。
通常情況下臼节,會(huì)要求接口的錯(cuò)誤信息越詳細(xì)越好,但這也不是一定的珊皿,也會(huì)有特殊情況网缝。
一般而言,前端會(huì)將后端接口的錯(cuò)誤信息原封不動(dòng)的顯示出來蟋定,因?yàn)榍岸撕茈y去判斷是否有涉密信息或者讓用戶難堪的信息粉臊。比如說A用戶屏蔽了B用戶,當(dāng)B用戶想看A用戶的詳情時(shí)驶兜,如果正確的返回:“A用戶已屏蔽B用戶扼仲,無法獲取”的話,會(huì)讓雙方都難堪抄淑。這時(shí)就需要返回模棱兩可的信息屠凶。這個(gè)就需要后端開發(fā)們自己去領(lǐng)悟。
針對默認(rèn)返回與API
維護(hù)
某些接口在發(fā)生錯(cuò)誤時(shí)會(huì)將HTML
返回肆资。特別是發(fā)生404矗愧、503等錯(cuò)誤時(shí),這種情況就比較常見郑原。當(dāng)發(fā)生這些錯(cuò)誤時(shí)唉韭,用于構(gòu)建API
的Web
服務(wù)器或者app
框架會(huì)直接返回出錯(cuò)信息,默認(rèn)情況下大都是HTML
犯犁。
但雖說是發(fā)生了錯(cuò)誤属愤,前端依然在訪問中,所以仍然期待服務(wù)器返回約定好的格式酸役,比如JSON
住诸。尤其在通過Accept
請求頭部或擴(kuò)展名等指定了接收格式時(shí)。當(dāng)然可以讓前端去檢查Content_Type
頭部簇捍,進(jìn)行相應(yīng)的處理只壳。但如果前端處理的不好或者沒有處理,可能會(huì)導(dǎo)致app
崩潰暑塑。
尤其是公共api
吼句,不能期望所有的使用者都嚴(yán)格遵循規(guī)范來處理好,這種api
算不上了好的api
事格。
關(guān)于API
的維護(hù)惕艳,正常來說搞隐,要避免不得不停止API
的發(fā)生。但特殊的時(shí)候也會(huì)不得不停止API
進(jìn)行維護(hù)工作远搪,這種情況需要返回503
狀態(tài)碼來告知前端當(dāng)前API
已經(jīng)停止工作劣纲。另外,因?yàn)檫@種停止操作不是意外而是有計(jì)劃進(jìn)行的谁鳍,所以要有API
何時(shí)重啟的時(shí)間信息癞季,將其發(fā)送給前端。
不僅要預(yù)備好用于定期維護(hù)的狀態(tài)碼和出錯(cuò)信息的返回倘潜,還要使用Retry-After
頭部來告訴前端維護(hù)結(jié)束的時(shí)間绷柒。從SEO
的角度來看,這個(gè)方式對普通的web
站點(diǎn)的維護(hù)也同樣適用涮因,也是Google
推薦的方法废睦。
Retry-After
的值可以是某個(gè)具體的日期或從當(dāng)前時(shí)刻算起至可正常訪問為止所需的秒數(shù)。
503 Service Temporarily Unavailable
Retry-After: Mon, 9 Sep 2020 20:00:00 GMT
從前端實(shí)現(xiàn)的角度來看养泡,在返回503錯(cuò)誤時(shí)嗜湃,是期待前端能識(shí)別出API
地方Retry-After
值指定的時(shí)間等待,然后在API
重啟的時(shí)候再次訪問澜掩。
雖然這些處理都取決于前端的具體實(shí)現(xiàn)购披,后端無法對此進(jìn)行控制,但依然要盡可能地返回詳細(xì)的信息输硝,方便前端處理并提升用戶體驗(yàn)今瀑。
總結(jié)
主要是三個(gè)痛點(diǎn):
- 必須選擇合適的
HTTP
狀態(tài)碼 - 向前端返回詳細(xì)的錯(cuò)誤信息
- 針對默認(rèn)返回與
API
維護(hù)
作者: zhangwinwin
鏈接:后端API接口的錯(cuò)誤信息返回規(guī)范
來源:github