后端API接口的錯(cuò)誤信息返回規(guī)范

前言

最近我司要制定開發(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ò)誤

下面主要來了解一下4xx5xx的錯(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)建APIWeb服務(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末程梦,一起剝皮案震驚了整個(gè)濱河市点把,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屿附,老刑警劉巖郎逃,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挺份,居然都是意外死亡褒翰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門匀泊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來优训,“玉大人,你說我怎么就攤上這事各聘〈Х牵” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵躲因,是天一觀的道長早敬。 經(jīng)常有香客問我忌傻,道長,這世上最難降的妖魔是什么搞监? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任水孩,我火速辦了婚禮,結(jié)果婚禮上琐驴,老公的妹妹穿的比我還像新娘俘种。我一直安慰自己,他們只是感情好绝淡,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布安疗。 她就那樣靜靜地躺著,像睡著了一般够委。 火紅的嫁衣襯著肌膚如雪荐类。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天茁帽,我揣著相機(jī)與錄音玉罐,去河邊找鬼。 笑死潘拨,一個(gè)胖子當(dāng)著我的面吹牛吊输,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铁追,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼季蚂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琅束?” 一聲冷哼從身側(cè)響起扭屁,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涩禀,沒想到半個(gè)月后料滥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艾船,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年葵腹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屿岂。...
    茶點(diǎn)故事閱讀 40,926評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡践宴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爷怀,到底是詐尸還是另有隱情阻肩,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布霉撵,位于F島的核電站磺浙,受9級特大地震影響洪囤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撕氧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一瘤缩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伦泥,春花似錦剥啤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至防楷,卻和暖如春牺丙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背复局。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工冲簿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亿昏。 一個(gè)月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓峦剔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親角钩。 傳聞我的和親對象是個(gè)殘疾皇子吝沫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評論 2 361