RESTful API接口設計規范與最佳實踐
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
Part1介紹RESTFull 接口設計目前廣泛應用于各種軟件系統中,特別是前后端分離架構的web應用。相信各位web應用的開發者對這個概念并不陌生,但是我們經常會遇到幾個這樣的疑惑或者問題:
在我們試圖搞清楚以上幾個問題之前,首先需要讀者了解或者閱讀過關于RESTfull的定義,這類定義百度一搜一大把這里就不重復贅述了。接著是最好你實踐過這類風格設計的接口,如果你心中也同樣有這幾個問題或者疑問那就更好了,當然最后這兩點要求并不是必須。 如果你已經閱讀過關于RESTfull的相關定義,你就會發現RESTfull是一種接口設計風格,它制定了一些原則條件,只要你遵守了,就算是RESTful風格的接口設計。 那么問題就來了,這里面就存在很多靈活空間了,比如說我部分遵守,部分不遵守,可以嗎?可以?;蛘哒f我在遵守的基礎上,再自定義一些行為,可以嗎?可以。 各種諸如此類的實踐路線導致了我們很難在開發生涯中真的看到有兩個或更多的接口實現了一模一樣的RESTfull風格接口,即便他們的業務是一樣的。這是因為RESTfull本身既然是一種設計風格,那么風格發揮的主動權自然就是在開發者身上,而且絕大多數的項目所開發的API接口都是對內或者有限對外開放的,所以對于RESTfull的實踐是否合格更多取決于內部團隊老大的看法。
這里我個人覺得有一部分原因是同行襯托,RESTfull基于HTTP協議,采用json格式的字符串作為傳輸內容,相對于過去的SOAP協議,采用XML格式標記語言來說,RESTfull無論從開發成本或者網絡傳輸來說都顯得輕量太多太多。而前面提到的,關于實際開發出來的RESTfull接口風格迥異的問題實際上并沒有太糟糕,為什么這么說呢?因為最起碼的一點是無論實際設計出來的接口再奇葩,總歸是基于HTTP協議和使用JSON字符串來傳遞數據,這最起碼保證了我們在調用別人設計好的接口的時候足夠簡單。 當然,能調用跟實際交互還有一段很長的距離,而中間這個過程你是否舒適,有一部分就體現在接口細節設計上了。按照一般的經驗,像這種”標準化“的設計,我們會封裝一些基礎方法來實現接口的調用和數據接收,但現實卻是無法實現的。因為RESfull接口的具體實現細節上是因人而異的,這就導致了我們封裝的調用或者解析代碼未必能夠完全復用,很典型的例子就是我們一開始拋出來的那幾個問題。 這時候讀者們肯定想說,還是想吐槽,是的,我們可以吐槽一個接口設計得很糟心,讓我們調用起來很難受,但是我們又不可否認他確實遵守了RESTfull的基本規定,你可以發送一個HTTP請求,通過JSON來提交和接收數據,你完全拿對方沒辦法。所以這也就是為什么我們一開始給出的答案是:沒有對錯。我們可以吐槽一個接口設計得非常糟糕,但是不能說這個接口不是RESTfull接口,但是,我們可以評判一個接口是否嚴格遵循了RESTfull風格設計以及遵循的程度有多高。 我們可以從開局的幾個問題入手來嘗試評判下相應的接口設計是否很好的遵循了RESTfull風格設計。 Part2為什么接口只設計了GET和POST兩種請求方法類型?
從上面的表格可以看出,不同類型的請求方法有著自己明確的含義,在理想的情況下,我們可以通過一個請求類型+請求地址的形式,直觀的看出一個接口的作用,比如:
這里讀者可以嘗試做一個閱讀理解。 那么這里問題就來了,既然HTTP的請求方法類型有助于我們理解一個接口的作用,為什么在有些接口中唯獨只會使用GET和POST呢?這里面我覺得原因有很多,有些可能我也想不到也猜不到,但是我從個人開發經驗上嘗試猜測一下。
坦白說,除了查詢請求這種無可爭議的使用GET之外,其他的全部歸為POST無疑是一件很方便的事。你不需要花時間去考慮接口的行為然后決定要定義成什么請求方法類型,反正具體的實現邏輯都是一樣的,而且POST方法的描述也似乎能涵蓋到其他幾個類型的請求方法。但這里讀者可能會說,在某些場景下會有歧義,比如說我們要調用一個接口實現刪除一個用戶:
這里我們復用了前面其中一道閱讀理解題并把類型改成了POST。這里第一眼看上去確實不能很好的表達接口的意圖,但是我們有接口文檔呀,我在相應的接口名稱中寫清楚再放大字體說這個接口是刪除用戶用的不就完事了?這么一聽好像也有道理。所以綜合看來,細分各個方法請求類型似乎變成一件很多余的事,吃力不討好,干脆就GET/POST一把梭了。 說到這里,我們再回過頭來看看問題本身,做錯了嗎?沒有。那嚴格遵循了RESTfull風格設計了嗎,那倒是并沒有。
遵循 RESTfull
不遵循RESTfull
從這里的示例可以看出,在不遵循RESTfull風格設計的情況下我們難免需要在接口URL地址中增加一些描述性的單詞,這會導致路由接口地址變得很冗長和不夠優雅,當然如果你覺得這不是什么問題那也是沒錯的,對,你沒錯。
Part3為什么接口是否請求成功,HTTP狀態碼永遠只會是200?
從上面表格可以看出,HTTP碼是用于標識本次請求響應的結果狀態,通過HTTP狀態我們可以直觀的判斷出本請求是不是成功的,但是為什么有些接口設計的情況是無論成功與否都只會返回200的狀態碼呢?
首先假設我們把所有請求響應的HTTP狀態碼都標識為200,那么我們必然需要在響應內容中增加一些字段來描述本次錯誤,例如:
這里大家可能會覺得,我們已經有code和message字段來描述本次請求的錯誤了,完全不需要HTTP狀態碼。這里乍一看是沒有問題的,前端也能在統一異常處理的層面很好的捕獲異常。 但是,當你的系統到了一定的規模(這個很容易達到,并不要求需要多大的規模體量,只要不是demo項目),你的錯誤類型就會有很多種,往往我們的錯誤碼清單會很長,當然這對于后端開發來說不是啥問題,因為這個信息其實是給前端開發者處理的,但是前端開發者在處理這些錯誤的時候就難受了。 難受在哪?假設我們現在有10個關于賬戶異常的錯誤碼,10個關于業務A的錯誤碼,10個關于業務B的錯誤碼,一共30個。這里面有個業務需求,就是某些特定的錯誤碼需要前端做出特定的行為,比如說跳轉到指定頁面,或者強制退出啥等等。那么這時候前端在統一異常處理的時候咋做?那就是各種 看起來似乎也問題不大嘛,是的,接著我們需求變了,和原來不一樣了,原來的分支判斷條件可能不適用了,錯誤碼改了,含義不一樣了,或者又增加了30個新的錯誤碼,那么這時候前端開發者就炸了。
比如說給后端傳遞了錯誤的參數,這種一般后端在校驗不通過的時候,會返回的HTTP狀態碼是400。這類提示信息是需要把具體錯誤信息展示給用戶作為警告提示的,那么前端開發者在統一異常處理的時候,只需要判斷HTTP狀態碼是不是400,是的話直接把具體內容以各種彈出提示的形式展示即可,不用關心具體的錯誤碼又是什么(需要特殊處理的除外)。還有一種是401和**403 **HTTP狀態碼的錯誤,這兩種都是跟權限有關的錯誤,前端開發者在做統一異常處理的時候也可以進行針對性的統一捕獲處理。
相對于單純依靠錯誤碼,HTTP狀態碼+錯誤碼的方式讓前端開發者更容易實現封裝和統一處理,前端開發者根據HTTP狀態碼定義不同的響應處理,可以大大減少開發工程量和降低溝通成本。但是這里讀者們可能會說,我們可以把錯誤碼按范圍劃分,實現比如1~99是代表XX類型錯誤,100~199是XX類型錯誤。這個確實可以,但是這等于是換了條路開倒車,其實還是會有一開始的提到的痛點問題出現。而且錯誤碼因為是團隊定義的,如果維護不善會導致各種前后端開發者信息不同步的問題,既然通過HTTP狀態碼的定義就能解決大部分問題了為什么不用呢? 最后總結一下這個問題就是,強烈建議嚴格按照HTTP狀態碼的定義區分接口響應的HTTP狀態碼,錯誤碼作為一種細分的補充。 Part4HTTP狀態碼不存在,返回 200 還是 404 ?問題: 當一個查詢的結果為空的時候,為什么有的接口設計會返回異常(HTTP狀態碼404或其他),有的則是會返回請求成功(HTTPS狀態碼200),但是返回結果是空數組或者null等表示結果為空的標識? 解析:這個問題情況有點特殊,理論上來說,當我們查詢了資源然后結果是不存在的時候,這個時候用404的HTTP狀態碼來標識本次請求的響應狀態是一點問題都沒有的,也是非常規范的做法。但是這是建立在業務場景規定,查詢結果為空的時候屬于異常的前提上。 1返回HTTP狀態碼 |
關鍵字查詢
相關文章
正在查詢... |