此文已由作者鄭華斌授權網易雲社群發布。
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 資源多重表示...