1. 程式人生 > 實用技巧 >後端API介面的錯誤資訊返回規範

後端API介面的錯誤資訊返回規範

前言

最近我司要制定開發規範。在討論介面返回的時候,後端的同事詢問我們前端,錯誤資訊的返回,前端有什麼意見?

所以做了一些調研給到後端的同事做參考。

錯誤資訊返回

在使用API時無可避免地會因為各種情況而導致介面返回錯誤的資訊。比如指定的query引數錯誤,又或者method不支援等,這些情況都會返回相關的錯誤資訊。另外伺服器不穩定或者停止運行了,也必須將錯誤資訊返回。

顯然,當錯誤發生的時候,只是籠統地返回“發生了錯誤”是不行的。如果前端不瞭解發生了什麼錯誤,也就不知道該怎麼去除錯,怎麼去修復這個bug。所以說,必須向前端返回儘可能多的資訊,以便前端找到出錯的地方解決問題。

通過HTTP狀態碼錶示出錯資訊

首先必須選擇合適的HTTP狀態碼,之前我司的後端API沒有遵循這個規則。例如API無論如何訪問,都會返回200狀態碼,只在返回訊息體中的描述是否發生錯誤。

HTTP/1.1 200 OK
Content-Type: application/json

{
    "error": {
        "code": 2002,
        "message": "Invalid parameter"
    }
}

雖然這麼處理前端也能理解API的錯誤資訊,但由於HTTP協議已經完整地定義了各個狀態碼所表示的含義,所以返回恰當的狀態碼才能提高前端正確識別錯誤的可能性。

如果出錯了,仍然返回200狀態碼,有可能導致前端的處理髮生混亂,這種情況要一定要禁止。特別是通用的API

,基本上都是先看狀態碼再決定下一步的處理,如果沒有返回正確的狀態碼,就會導致前端無法執行適當的方法去處理,從而引發各種不必要的問題。而且這種做法沒有儘可能地運用HTTP協議,也給前端編寫錯誤處理增加了難度。

  • 狀態碼分類
狀態碼含義
1xx 訊息
2xx 成功
3xx 重定向
4xx 前端原因引起的錯誤
5xx 伺服器原因引起的錯誤

下面主要來了解一下4xx5xx的錯誤碼:

4xx-前端發生了錯誤

4xx的狀態碼主要是用於描述因前端請求的問題而引發的錯誤,也就是說伺服器端不存在出錯問題,但伺服器端無法理解前端的請求,或者能理解但無法處理的請求。這一類的錯誤,統一使用4xx

錯誤碼。

狀態碼名稱說明
400 Bad Request 表示其他錯誤,就是4xx都無法描述的前端發生的錯誤
401 Authentication 表示認證型別的錯誤
403 Authorization 表示授權的錯誤(認證和授權的區別在於:認證表示“識別前來訪問的是誰”,而授權則是“賦予特定使用者執行特定操作的許可權”)
404 Not Found 表示訪問的資料不存在
405 Method Not Allowd 表示可以訪問介面,但是使用的HTTP方法不允許
406 Not Acceptable 表示API不支援前端指定的資料格式
408 Request Timeout 表示前端傳送的請求到伺服器所需的時間太長
409 Confilct 表示資源發生了衝突,比如使用已被註冊郵箱地址註冊時,就引起衝突
410 Gone 表示訪問的資源不存在。不單表示資源不存在,還進一步告知該資源該資源曾經存在但目前已消失
413 Request Entity Too Large 表示請求的訊息體過長而引發的錯誤
414 Request-URI Too Large 表示請求的首部過長而引發的錯誤
415 Unsupported Media Type 表示伺服器端不支援客戶端請求首部Content-Type裡指定的資料格式
416 Range Not Satisfiable 表示無法提供Range請求中的指定的那段包體
417 Expectation Failed 表示對於Expect請求頭部期待的情況無法滿足時的響應碼
421 Misdirected Request 表示伺服器認為這個請求不該發給它,因為它沒能力處理
426 Upgrade Required 表示伺服器拒絕基於當前HTTP協議提供服務,通過Upgrade頭部告知客戶端必須升級協議才能繼續處理
428 Precondition Required 表示使用者請求中缺失了條件類頭部,例如If-Match
429 Too Many Requests 表示客戶端傳送請求的速率過快
431 Request Header Fields Too Large 表示請求的HEADER頭部大小超出限制
451 Unavailable For Legal Reasons 表示由於法律原因不可訪問

5xx-伺服器端發生錯誤

5xx狀態碼錶示錯誤由伺服器端的問題引發的。

狀態碼名稱說明
500 Internal Server Error 表示伺服器內部錯誤,且不屬於以下錯誤型別
501 Not Implemented 表示伺服器不支援實現請求所需要的功能
502 Bad Gateway 代理伺服器無法獲取到合法資源
503 Service Unavailable 伺服器資源尚未準備好處理當前請求
504 Gateway Timeout 表示代理伺服器無法及時的從上游獲得響應
505 HTTP Verson Not Supported 表示請求使用的HTTP協議版本不支援
507 Insufficient Storage 表示伺服器沒有足夠的空間處理請求
508 Loop Detected 表示訪問資源時檢測到迴圈
511 Network Authentication Required 表示代理伺服器發現客戶端需要進行身份驗證才能獲得網路訪問許可權

向前端返回詳細的錯誤資訊

當錯誤發生時,除了需要返回相應的狀態碼之外,還需要返回詳情的錯誤資訊。因為狀態碼只是通用的描述錯誤的類別,一般無法表示實際發生的具體錯誤資訊。

比如說400狀態碼,只是知道前端請求發生了錯誤,至於如何去修改,僅憑這個是沒有辦法找到bug的。

通常來說:返回錯誤資訊的方法有兩種:

  • 將資訊放入HTTP響應頭
  • 將資訊通過HTTP響應體返回

1、通過自定義頭部,將詳細的錯誤資訊放入響應頭中

X-ERROR-CODE: 2020
X-ERROR-MESSAGE: Bad authentication token
X-ERROR-INFO: http://api.example.com/v1/authentication

2、將錯誤資訊放入響應體中

{
    "error": {
        "code": 2020,
        "message": "Bad authentication token",
        "info": "http://api.example.com/v1/authentication"
    }
}

從前端的角度來考慮,通過響應體返回會更加容易處理。

這裡的錯誤程式碼的命名方式,按照後端自己的要求編寫即可。

通常情況下,會要求介面的錯誤資訊越詳細越好,但這也不是一定的,也會有特殊情況。
一般而言,前端會將後端介面的錯誤資訊原封不動的顯示出來,因為前端很難去判斷是否有涉密資訊或者讓使用者難堪的資訊。比如說A使用者遮蔽了B使用者,當B使用者想看A使用者的詳情時,如果正確的返回:“A使用者已遮蔽B使用者,無法獲取”的話,會讓雙方都難堪。這時就需要返回模稜兩可的資訊。這個就需要後端開發們自己去領悟。

針對預設返回與API維護

某些介面在發生錯誤時會將HTML返回。特別是發生404、503等錯誤時,這種情況就比較常見。當發生這些錯誤時,用於構建APIWeb伺服器或者app框架會直接返回出錯資訊,預設情況下大都是HTML

但雖說是發生了錯誤,前端依然在訪問中,所以仍然期待伺服器返回約定好的格式,比如JSON。尤其在通過Accept請求頭部或副檔名等指定了接收格式時。當然可以讓前端去檢查Content_Type頭部,進行相應的處理。但如果前端處理的不好或者沒有處理,可能會導致app崩潰。

尤其是公共api,不能期望所有的使用者都嚴格遵循規範來處理好,這種api算不上了好的api

關於API的維護,正常來說,要避免不得不停止API的發生。但特殊的時候也會不得不停止API進行維護工作,這種情況需要返回503狀態碼來告知前端當前API已經停止工作。另外,因為這種停止操作不是意外而是有計劃進行的,所以要有API何時重啟的時間資訊,將其傳送給前端。

不僅要預備好用於定期維護的狀態碼和出錯資訊的返回,還要使用Retry-After頭部來告訴前端維護結束的時間。從SEO的角度來看,這個方式對普通的web站點的維護也同樣適用,也是Google推薦的方法。

Retry-After的值可以是某個具體的日期或從當前時刻算起至可正常訪問為止所需的秒數。

503 Service Temporarily Unavailable
Retry-After: Mon, 9 Sep 2020 20:00:00 GMT 

從前端實現的角度來看,在返回503錯誤時,是期待前端能識別出API地方Retry-After值指定的時間等待,然後在API重啟的時候再次訪問。

雖然這些處理都取決於前端的具體實現,後端無法對此進行控制,但依然要儘可能地返回詳細的資訊,方便前端處理並提升使用者體驗。

總結

主要是三個痛點:

  • 必須選擇合適的HTTP狀態碼
  • 向前端返回詳細的錯誤資訊
  • 針對預設返回與API維護

作者: zhangwinwin
連結:後端API介面的錯誤資訊返回規範
來源:github