總結常見的違背Rest原則的介面設計做法

2021-09-25 13:25:07 字數 3153 閱讀 1432

此文已由作者鄭華斌授權網易雲社群發布。

rest這詞我們常常掛在嘴邊,比如「開發乙個rest介面」,又比如spring專案的**:

}commoncontroller使用了@restcontroller註解,顧名思義,告訴讀者這是乙個rest介面的實現。然而以@restcontroller註解的介面卻不一定符合rest原則。結合最近的專案,總結下常見的違背rest設計的一些做法。

典型的錯誤做法:無論什麼請求,一律用post,或者『增刪改』用post,『查』用get。

其實rest有個原則叫統一介面(uniform inte***ce),統一介面原則建議了各http方法的使用場合,

get:獲取資源,返回訊息頭和訊息表示,即header和body。

head:獲取資源元資料,返回訊息頭

delete:刪除資源

post:rest設計中,post通常用來為乙個已有資源建立乙個從屬資源(subordinate resource),如aws s3的post object(或者稱web post)介面。

put:建立或修改乙個資源

put和post的區別比較微妙,這裡拿aws s3(或者參考網易物件儲存nos)的介面設計來舉例。其中aws s3的詳細api文件參見: s3有兩種資源,桶(bucket)和物件(object),物件從屬於某個桶。

建立乙個桶的介面為:

host: s3.amazonaws.com建立/修改乙個物件的put object介面為:

host: s3.amazonaws.com[物件資料]aws s3同時提供了post object介面,同樣可以建立/修改乙個物件,如下

post /bucketname http/1.1host: s3.amazonaws.comcontent-type: multipart/form-data; boundary=9431149156168[包含物件資料的body]
獲取物件的get object介面為:

host: s3.amazonaws.com同樣的建立/修改乙個物件,乙個用put方法,另乙個用post方法,為什麼?關鍵在於url,put請求的目標url(這裡為/bucketname/objectname),就是將來用於獲取該物件的url,即put object和get object的url是一致的。但是post object的url與get objecturl不一樣,post 請求只知道父資源的url(即/bucketname),表示在該父資源下建立新資源,至於新資源的確切url,是由伺服器決定的,一般來說是post請求的響應應該包含乙個location訊息頭,其包含新建從屬資源的url。

安全性safe和冪等性idempotent

rest設計還應該遵循安全性和冪等性約束,如下:

get和head應當是安全的:get和head請求不應該導致伺服器狀態發生改變

統一介面原則的好處:

給乙個資源uri,不用看文件就知道可以有get、delete等操作及其意義,世界通用。

安全性和冪等性增加了http的可靠性:如果請求沒成功(但也許已成功了),只需重新發一次即可,不用擔心***。

典型的錯誤做法:無論成功失敗,http code一律返回200,具體錯誤資訊交由json body裡的內容來判斷,舉例如下,

某甲服務***介面的響應如下

http/1.1 200 ok
某乙服務***介面的響應如下

}其實restful的設計的乙個標誌特徵是充分並正確利用http響應碼,典型的如:

設計rest介面應該遵循上面的響應碼,語義明確並通用。如果像上面例子那樣,任何情況都一律返回200,而具體成功與否需要到http響應訊息體裡去解析,而且不同的服務或開發者自定義訊息體的格式,那麼服務呼叫方就需要針對不同的服務寫不同的判斷邏輯,增加系統互動複雜性。

有些通用的客戶端,會針對301自動處理重定向,針對500以上的響應自動重試,而一律返回200的設計是沒法使用這些特性的,只能呼叫方一一自個處理。

典型的錯誤做法:設計的uri是面向操作而不是面向資源的,舉例如下,

某系統 設計的渠道相關的uri是這樣的:

新增渠道

post /xhr/thirdparty/admin/channel/add.json?
編輯渠道

post /xhr/thirdparty/admin/channel/update.json?
刪除渠道

post /xhr/thirdparty/admin/channel/delete.json?channelid=id
這裡的介面設計有三個特點:

http方法都是post;

uri裡攜帶操作資訊,如uri裡出現「add」,「update」,「delete」等字眼;

同乙個資源由於操作不一樣而uri不一樣。

其實rest式的設計中,uri即是資源的名稱,也是資源的位址,因為不同的操作而資源位址不一樣是不合適的。資源的操作(方法資訊)應該由統一介面來表示,即http 方法put、post、get、delete等,而不應該放到uri中。

對照統一介面和面向資源這兩個特徵來設計,上面的介面restful化可以是這樣的:

新增渠道

post /xhr/thirdparty/admin/channel

[渠道具體資訊]

修改渠道

put /xhr/thirdparty/admin/channel?channelid=id 或者put /xhr/thirdparty/admin/channel/$

[渠道具體資訊]

刪除渠道

delete /xhr/thirdparty/admin/channel?channelid=id或者delete /xhr/thirdparty/admin/channel/$
渠道的位址為/xhr/thirdparty/admin/channel?channelid=id或者/xhr/thirdparty/admin/channel/$,重在url唯一。

《restful web services》

總結常見的違背Rest原則的介面設計做法

此文已由作者鄭華斌授權網易雲社群發布。rest這詞我們常常掛在嘴邊,比如 開發乙個rest介面 又比如spring專案的 commoncontroller使用了 restcontroller註解,顧名思義,告訴讀者這是乙個rest介面的實現。然而以 restcontroller註解的介面卻不一定符合...

REST落地的實現原則

rest 表象化狀態轉變 rest模式的web服務與複雜的soap和xml rpc對比來講明顯的更加簡潔,越來越多的web服務開始採用rest風格設計和實現.rest落地的實現原則 1 所有資源都有定義id uri 在web中,代表id的統一概念是 uri。uri構成了乙個全域性命名空間,使用uri...

關於Rest的關鍵原則

參考 關於rest的關鍵原則 1 為所有事物定義id 後台的每乙個資源都可以定義乙個uri 2 事物鏈結在一起 3 標準方法 使用http協議中的方法來定義介面 class resource 如圖 即 orders get表示獲取所有訂購資訊,orders post新增乙個訂購資訊 4 資源多重表示...