熱線電話:13121318867

登錄
首頁大數據時代別吵了,RestAPI的狀態碼和錯誤處理最佳實踐來了
別吵了,RestAPI的狀態碼和錯誤處理最佳實踐來了
2021-03-10
收藏

來源:麥叔編程

作者:麥叔

代碼評審會上,氣氛有點緊張!

別吵了,RestAPI的狀態碼和錯誤處理最佳實踐來了

羅老師正在看張三的代碼,并指出了一個問題:

你這個API,在用戶沒登錄的情況下,應該返回401,不應該返回200。要遵守HTTP協議的規范。

張三對此不以為然的說:

我們約定了都返回200的,具體的錯誤信息放在返回的JSON里。我又沒有違法,不能為了規范而規范吧。

羅老師竟無言以對。他趕快去查看Facebook,谷歌等業界大亨的做法,可是他們的做法也不統一。到底要不要遵守HTTP Status Code呢?

聽我細細道來,本文涵蓋:

  • HTTP和Rest API的基本知識
  • Rest API使用HTTP Status Code的最佳實踐
  • Rest API的錯誤處理最佳實踐

HTT協議和Restful API

你很可能已經熟悉HTTP和Restful API。不管你是否熟悉,讓我們用1分鐘的時間來簡單回顧一下:

HTTP協議定義了瀏覽器和網頁服務器之間的交互過程。它的核心概念就2個:

  • Request - 瀏覽器要打開一個網頁,給服務器發送一個Request,里面包含了網址,參數,及其他信息。
  • Response - 服務器返回一Response給瀏覽器,包括狀態碼,比如200表示成功,4xx和5xx都表示不同類型的失敗,以及網頁的具體內容。

有了標準的協議就好辦了,任何人都可以開發瀏覽器出來,只要你寫的軟件都能遵守這個協議就行。我記得我研究生時候一門課的大作業就是開發一個簡易的瀏覽器。

控制了瀏覽器,就控制了網絡流量,就不怕沒錢賺了,所以各大廠商都在努力推廣自己的瀏覽器,就有了IE, Edge,Chrome,FireFox,QQ瀏覽器,以及360瀏覽器等。有的瀏覽器又好用又文明,有的瀏覽器很流氓,有的瀏覽器不遵守協議,讓開發人員恨得牙根癢癢。

Rest API說白了就是一個網頁地址,不過它只返回JSON或者XML格式的數據,而不是HTML網頁。

HTTP Status Code

每個HTTP的Response都包含一個Status Code,表示請求的狀態,是成功,還是失敗,失敗的原因是什么等等。

HTTP的Status Code一共有幾十個,詳細列表可以查看相關標準。但絕大部分人平時只會接觸到最常見的少于10個的代碼:

代碼

含義

說明

200

請求成功


201

創建成功

專門用于創建新的記錄的時候

301

永久重定向

網址永久變更成另外一個網址

302

臨時重定向

網址臨時變更成另外一個網址

400

無效的請求

請求的網址無效等

401

沒有登錄

需要登錄才能訪問

403

沒有權限

雖然登陸了,但是沒有權限

404

請求資源不存在

請求的東西不存在,比如某個人的信息

500

服務器端錯誤

服務器端發生了錯誤

有了這套標準,處理請求的程序首先根據狀態碼判定請求是否成功,然后做相應的處理。

Rest API是否應該遵循HTTP Status Code

Rest API理論上也應該遵守HTTP的規定,根據不同的情況,返回相應的狀態碼。但理論只是理論,大家對此的認識是不同的?;旧戏殖闪藘膳桑?

  • 200派:不管對錯,一律返回200,在返回的JSON中再具體指明錯誤的原因。
  • 正規派:另外一派堅持使用規范的HTTP狀態碼。如果是沒有登錄,就返回401,如果是沒權限就返回403。

這兩派都有重量級的公司參與,比如FaceBook就是200派,而Google, Twilio等是正規派:

別吵了,RestAPI的狀態碼和錯誤處理最佳實踐來了

200派的理由很簡單:反正我都需要處理返回的JSON,干脆我就把具體狀態寫在JSON里面,就不用管HTTP的狀態碼了,都用200好了。你看Facebook這樣的大公司都用200了。

而正規派的人的理由就顯得略微有點不正規,大部分人說:因為這是規范。Rest API是基于HTTP的,就應該遵守HTTP的狀態碼。

我是正規派的人,但我也覺得上面的理由有點薄弱。到底有什么好處?在什么情況下有好處?拿點實實在在的好處或者理由來?

首先,這肯定不是一個非黑即白的問題,200派和正規派都是可行的。只要API的提供者和請求者協調好,都不會帶來很大的問題。但是我們仍然應該適度遵守HTTP的狀態碼。實實在在的理由如下:

  1. 作為一個開放的API,可能會被不同的消費者使用。為了最大限度的適應不同的消費者,最好的方法就是大家遵守一個業界規范,那就是HTTP的狀態碼。下面的2點都是舉例來證明第1點。
  2. 很多JavaScript框架設計上就是基于HTTP協議的,根據不同的狀態碼做不同的處理,比如下面的JQuery的Ajax請求就可以根據HTTP的狀態碼執行不同的代碼塊:$.ajax({
    url: 
    'https://maishucode.com/page/2',
    type: 
    'GET',
    success: 
    function(data){
    alert(
    '成功返回'); //返回2xx,執行這個代碼塊
    }, error: 
    function(data) {
    alert(
    '出錯啦!'); //返回4xx或者5xx,執行這個代碼塊
    }});
    如果API沒有正確的使用HTTP狀態碼,上面的代碼中需要手動解析JSON里面的狀態碼,再做分支的判斷。
  3. 為了通用,很多中間系統根據狀態碼來分析系統的訪問數據,比如ELK可以根據HTTP的狀態碼分析有多少成功的請求,多少失敗的請求。如果都統一返回200,那么就沒法分析出:有哪些未登錄的訪問,有哪些未授權的訪問,有多少服務器端錯誤等。但是這里有利也有弊,有些流氓的中間系統會根據狀態碼劫持網頁,比如有些瀏覽器和路由器就會劫持404網頁,顯示它自己的廣告頁。具體做法是:當路由器或者瀏覽器發現請求返回的是404,它們就會丟掉Response,而顯示一個自己的廣告網頁。這種劫持是非常無恥的行為。404也是服務器返回給請求者的一個消息,網頁仍然可能包含重要的內容。再說了,不管什么消息,中間人都不應該劫持。
別吵了,RestAPI的狀態碼和錯誤處理最佳實踐來了
  • 總結一下,我支持使用合理的HTTP狀態碼的。原因上面已經說了。但是慎用404,因為可能會被眾多流氓劫持。但是還有兩點:
  • 不要濫用HTTP狀態碼,基本上就用我前面列舉出來的那些就夠了。
  • 使用HTTP狀態碼后,仍然需要使用和業務相關的狀態碼。這就是下面要說的。

Rest API的錯誤處理最佳實踐

使用了HTTP狀態碼以后,讓API符合了一定的標準,這很好。但HTTP狀態碼不能涵蓋我們具體的業務場景,我們仍然需要定義和業務場景相對應的錯誤碼。下面我推薦一個錯誤處理的返回格式,舉例如下:

{ "status":403,
   "error": {     
      "code":'40041',      
      "message":"用戶缺少訪問特工名單權限",     
      "moreInfo":"https://maishucode.com/errors/40041", 
      "traceId":"9527"      }, 
   "data":{
  }
}

下面是對每個字段的解釋:

  • status: HTTP狀態碼,不能為空,必須和HTTP header中的狀態碼一致。
  • code: 具體業務代碼,可以為空。這里需要技術人員和業務人員一起定義一套錯誤代碼規則。
  • message: 對錯誤信息的簡單解釋
  • moreInfo: 對錯誤信息的詳細解釋的網址。包含錯誤的詳細解釋,可能的原因,如何修正等。
  • traceId: 通過這個字段可以去日志文件中查找和本次操作相關的日志。
  • data: 存放具體的業務數據。

我要說的說完了!雖然這沒有絕對的對錯,但是符合良好的規范,提供充分的信息給調用用肯定是沒錯的。你覺得呢?在留言區留下你的意見吧!

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢