Code狀態碼碼是接口設計中的常見概念,本文主要討論接口開發中Code碼設計。從客戶端和服務器端開發的角度,給出具體的工程實踐建議和思考。前端
從筆者以前的一份接口文檔定義開始提及,文檔中定義的服務端接口輸出格式以下node
返回數據由兩部分構成,第一部分是對結果集的說明,第二部分是data節點ios
{ "code": 4302, "message": "no sign", "time": 1487832032, "data": [] }
第一部分,不管錯誤與否,都會有以下片斷。nginx
code:信息代號git
message:信息描述github
time:接口返回時間web
第二部分是具體數據以下:編程
data節點json
咱們能夠 看到code=4302,4302並非一個HTTP 協議狀態碼,而是一個業務狀態碼,是業務領域的含義,並不是咱們常見的HTTP 協議層面的響應狀態碼。axios
在REST 接口設計規範中,咱們一般都會被引導爲這裏的Code 應該是HTTP 協議狀態碼 200,404 或者501等。
實際上這是實踐中的一種折中的方式,Code 會包含HTTP狀態碼和業務狀態碼
業界爲何會有這種實踐,與客戶端的解析數據方式有很大關係,下文中會給出答案。
說到這裏,咱們引出了兩個概念,一個是業務狀態碼,一個是HTTP請求狀態碼。
兩個概念很好理解
業務狀態碼是服務端給出的關於業務描述的碼,用於客戶端明確得知本次請求的資源的狀態狀況。上文例子中的4032被認爲是一個缺乏簽名sign的業務狀態碼。有業務狀態碼輸出代表當次HTTP 請求是通的。
業務狀態碼是可變的,沒有業界標準,是一種資源狀態描述,與HTTP響應狀態碼也不存在對應關係。
以下文圖片HTTP-200 顯示,接口是通的 HTTP 狀態響應返回 200,可是業務沒有執行成功,code用1 表示。
HTTP/1.1 200 OK Server: nginx Date: Wed, 13 Nov 2019 01:27:03 GMT Content-Type: application/json; charset=UTF-8 Transfer-Encoding: chunked Connection: close X-Powered-By: PHP/5.6.15 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, PUT, GET, DELETE, OPTIONS Access-Control-Allow-Headers: token, app-key, content-type, etcp-base Access-Control-Max-Age: 86400 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff { "code": 1, "message": "states is wrong", "data": [] }
HTTP請求狀態碼是HTTP協議的一部分,用於代表HTTP響應狀態。
HTTP 狀態碼是HTTP 協議的工程實現,不符合協議規定的服務器端實現,咱們能夠認爲 服務器的HTTP 實現是錯誤的。
這裏舉一個簡單的冪等性例子,咱們知道DELETE 方法是冪等的,若是以前已經刪除過特定的資源,再次請求時也應該返回200的響應碼,而不是404資源不存在的響應。
爲何上文中着重介紹狀態碼的兩種分類,由於在業界開發中,這兩種碼會交叉使用,都有具體的使用場景,語義上不該該被混淆。
這裏拋出幾個問題
如何用Code碼代表這次訪問是鏈接成功的如何用Code碼代表這次訪問達到了客戶端預想的結果
客戶端應該先接收HTTP狀態碼仍是業務狀態碼
先對本文中的客戶端作一個簡單定義,即調用服務器端接口的調用者,主要是前端WebView,安卓和iOS工程師,統稱大前端。前端WebView的請求會涉及到跨域CORS
其實簡單來講,客戶端工程師最關心兩個問題:
第一,接口有沒有通。
第二,接口有沒有返回我想要的數據。
有經驗的客戶端工程師會關心接口若是不通,返回提示是否能夠指導我排除錯誤,或者說跟蹤到問題所在。接下來接口設計是否合理,是否有隱患,就看工程師職業水平和職業素養了。
客戶端HTTP 請求的通用方法是採用排除法,什麼是排除法,客戶端在請求服務端的REST 接口時,會先在網絡層面判斷接口是否通,包括404或者200。客戶端只關心自己有用的Code,其他都按異常處理。
網絡層判斷這個任務客戶端會交給具體的HTTP 攔截器 (Intercept),以後纔會接受當次接口的描述信息也就是data 和code,作業務前端處理。
axios 就是一個主要用於瀏覽器請求的HTTP 客戶端,包含請求響應攔截器(Intercept request and response)
Promise based HTTP client for the browser and node.js
如下代碼是兩段響應攔截,分別是攔截HTTP 協議的401驗證不經過和自定義業務代碼的驗證不經過。
axios.interceptors.response.use(function (res) { return res.data; }, function (res) { let response = res && res.response || {}; if (response.status == 401) { tool.showToast('登陸已過時,請從新登陸。'); tool.removeReUserInfo(); location.hash = "#/login"; } else { tool.showToast('請求數據失敗,請稍後再試。'); } });
axios.interceptors.response.use(function (res) { Indicator.close(); //首先關閉全部的提示窗口 var data = res.data; if (data.code == 4034) { //簽名不合法 tool.showToast('簽名不合法。'); } else if (data.code == 4033) { //token失效 tool.showToast('登陸已過時,自動登陸中。'); tool.removeUserInfo(); location.hash = "#/login"; } else { return data; } }, function (err) { // alert(JSON.stringify(err)); Indicator.close(); //首先關閉全部的提示窗口 tool.showToast('請求數據失敗,請稍後再試。'); });
okhttp 是一個安卓平臺的HTTP 客戶端,其中包含一個網絡攔截器(Network Interceptors)。網絡狀態碼和業務狀態碼的截取都交給攔截器處理處理。
這裏咱們從新梳理以前提出的三個問題,給出一些解決思路,同時總結一些經驗
如何用Code碼代表這次訪問是鏈接成功的?
這裏應該以HTTP 狀態碼爲依據,主要有200, 401 ,代表請求是【觸碰到關於的數據處理的業務部分了】如
HTTP/1.1 200 OK { "code": 0, "message": "客戶端已經是最新版本", "data": { "code": 10 }, "debug_stack": [] }
HTTP/1.1 401 Unauthorized Server: nginx { "name": "Unauthorized", "message": "Token is expired", "code": 401, "status": 401, "type": "yii\\web\\HttpException" }
如何用Code碼代表這次訪問達到了客戶端預想的結果?
這裏以業務狀態碼的數據爲依據,獲取到的就是真實的。Code能夠用 0 表示。
{ "code": 0, "message": "客戶端已經是最新版本", "data": { "code": 10 }, "debug_stack": [] }
客戶端應該先接收HTTP 狀態碼仍是業務狀態碼?
固然是先接收HTTP 狀態碼,其次是業務狀態碼,不混淆,也不能混淆。從軟件分層的角度來講,接收HTTP 狀態碼在接收業務狀態碼的上層,一般由攔截器來作,好比token過時的401阻擋。
通常狀況下,0表示成功,1表示業務操做失敗。業務複雜時,須要維護多種業務狀態碼。下圖是微信平臺的業務狀態碼枚舉,場景較多。
接口字段整齊
這裏所說的字段整齊是指服務提供方給到的數據結構是完整的,最通用的,如今大部分接口格式以下
三個字段應該都存在,能夠爲空,避免NULL。
{ "code": 200, "data": null, "message": "成功" }
對於提供接口開發的服務者而言,code和message字段都會給出,存在異議的字段是data。更嚴謹的說法是 請求的資源描述中夥包含資源狀態編碼和描述信息,如message。
當data 沒有數據時,有的工程師喜歡把data置爲null,或者直接不返回data字段。這兩種方式都不合理,都會增長調用方的判斷成本,尤爲是null,若是調用方寫法不嚴謹的話,很容易引起程序異常。
接口總會有返回值,data字段就是實際的返回值,能夠是空字符串,空數組,bool類型。
圖靈獎得主Tony Hoare 曾經公開表達過null是一個糟糕的設計,null老是表明着不肯定性。
業務狀態碼和異常是兩個概念,切忌混淆。業務狀態碼指正常的業務處理結果的顯示說明,而異常一般因爲語法錯誤,數據缺失形成程序不能正常執行完成。不能經過業務狀態碼而屏蔽異常。
本文從接口文檔開始,引出了狀態碼的概念,細分爲網絡狀態碼和業務狀態碼。結合服務器端和客戶端的編程角度,介紹了各自的使用場景。在分佈式服務化的網絡架構中,清晰的網絡狀態碼和業務狀態碼有助於服務鏈路的跟蹤和服務的鏈路跟蹤,尤爲是異常的定位和捕獲。業務狀態碼應該趨於同一化,與網絡狀態碼相互補充。
參考文檔中給出一些資源,有興趣的讀者能夠參考閱讀。