REST 架構該怎麼生動地理解?

@Ivony 老師的一句話概括很精闢:
URL定位資源,用HTTP動詞(GET,POST,DELETE,DETC)描述操作。

--- 簡潔版 ---

0. REST不是"rest"這個單詞,而是幾個單詞縮寫。但即使那幾個單詞說出來,也無法理解在說什麼 -_-!! (不是要貶低人,是我自己也理解困難);
1. REST描述的是在網絡中client和server的一種交互形式;REST本身不實用,實用的是如何設計 RESTful API(REST風格的網絡接口);
2. Server提供的RESTful API中,URL中只使用名詞來指定資源,原則上不使用動詞。“資源”是REST架構或者說整個網絡處理的核心。比如:
api.qc.com/v1/newsfeed: 獲取某人的新鮮; 
api.qc.com/v1/friends: 獲取某人的好友列表;
api.qc.com/v1/profile: 獲取某人的詳細信息;
3. 用HTTP協議裏的動詞來實現資源的添加,修改,刪除等操作。即通過HTTP動詞來實現資源的狀態扭轉:
GET 用來獲取資源,
POST 用來新建資源(也可以用於更新資源),
PUT 用來更新資源,
DELETE 用來刪除資源。
比如:
DELETE http://api.qc.com/v1/friends: 刪除某人的好友 (在http parameter指定好友id)
POST http://api.qc.com/v1/friends: 添加好友
UPDATE api.qc.com/v1/profile: 更新個人資料

禁止使用: GET api.qc.com/v1/deleteFri
圖例:

4. Server和Client之間傳遞某資源的一個表現形式,比如用JSON,XML傳輸文本,或者用JPG,WebP傳輸圖片等。當然還可以壓縮HTTP傳輸時的數據(on-wire data compression)。
5. 用 HTTP Status Code傳遞Server的狀態信息。比如最常用的 200 表示成功,500 表示Server內部錯誤等。

主要信息就這麼點。最後是要解放思想,Web端不再用之前典型的PHP或JSP架構,而是改爲前段渲染和附帶處理簡單的商務邏輯(比如AngularJS或者BackBone的一些樣例)。Web端和Server只使用上述定義的API來傳遞數據和改變數據狀態。格式一般是JSON。iOS和Android同理可得。由此可見,Web,iOS,Android和第三方開發者變爲平等的角色通過一套API來共同消費Server提供的服務。


--- 詳細版 ---

先說REST名稱
REST:REpresentational State Transfer = 直接翻譯:表現層狀態轉移。這個中文直譯經常出現在很多博客中。尼瑪誰聽得懂“表現層狀態轉移”?這是人話嗎?
首先,之所以晦澀是因爲前面主語被去掉了,全稱是 Resource Representational State Transfer:通俗來講就是:資源在網絡中以某種表現形式進行狀態轉移。分解開來:
Resource:資源,即數據(前面說過網絡的核心)。比如 newsfeed,friends等;
Representational:某種表現形式,比如用JSON,XML,JPEG等;
State Transfer:狀態變化。通過HTTP動詞實現。

REST的出處
Roy Fielding的畢業論文。這哥們參與設計HTTP協議,也是Apache Web Server項目(可惜現在已經是 nginx 的天下)的co-founder。PhD的畢業學校是 UC Irvine,Irvine在加州,有着充裕的陽光和美麗的海灘,是著名的富人區。Oculus VR 的總部就坐落於此(虛擬現實眼鏡,被FB收購,CTO爲Quake和Doom的作者 John Carmack)。
衆說周知,論文都是晦澀難懂的。當年在CMU讀書的時候,很多課程都會安排每週兩篇的Paper review。現在回想起來每次寫Paper review都是我最爲痛苦的時候。REST這篇博士論文毫無疑問更甚。
論文地址:Architectural Styles and the Design of Network-based Software Architectures
REST章節:Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST)
REST那章我初讀了,整個論文沒有讀完 =_=

RESTful API
實用的是如何正確地理解 RESTful架構和設計好RESTful API。

首先爲什麼要用RESTful結構呢?
大家都知道"古代"網頁都是前端後端融在一起的,比如之前的PHP,JSP等。在之前的桌面時代問題不大,但是近年來移動互聯網的發展,各種類型的Client層出不窮,RESTful可以通過一套統一的接口爲 Web,iOS和Android提供服務。另外對於廣大平臺來說,比如Facebook platform,微博開放平臺,微信公共平臺等,它們不需要有顯式的前端,只需要一套提供服務的接口,於是RESTful更是它們最好的選擇。在RESTful架構下:

Server的API如何設計才滿足RESTful要求?
首先是簡潔版裏面的那幾點。外加一些附帶的 best practices:
1. URL root:
example.org/api/v1/*
api.example.com/v1/*
2. API versioning:
可以放在URL裏面,也可以用HTTP的header:
/api/v1/
3. URI使用名詞而不是動詞,且推薦用複數。
BAD
  • /getProducts
  • /listOrders
  • /retrieveClientByOrder?orderId=1
GOOD
  • GET /products : will return the list of all products
  • POST /products : will add a product to the collection
  • GET /products/4 : will retrieve product #4
  • PATCH/PUT /products/4 : will update product #4
4. 保證 HEAD 和 GET 方法是安全的,不會對資源狀態有所改變(污染)。比如嚴格杜絕如下情況:
GET /deleteProduct?id=1
5. 資源的地址推薦用嵌套結構。比如:
GET /friends/10375923/profile
UPDATE /profile/primaryAddress/city
6. 警惕返回結果的大小。如果過大,及時進行分頁(pagination)或者加入限制(limit)。HTTP協議支持分頁(Pagination)操作,在Header中使用 Link 即可。
7. 使用正確的HTTP Status Code表示訪問狀態:HTTP/1.1: Status Code Definitions
8. 在返回結果用明確易懂的文本(String。注意返回的錯誤是要給人看的,避免用 1001 這種錯誤信息),而且適當地加入註釋。
9. 關於安全:自己的接口就用https,加上一個key做一次hash放在最後即可。考慮到國情,HTTPS在無線網絡裏不穩定,可以使用Application Level的加密手段把整個HTTP的payload加密。有興趣的朋友可以用手機連上電腦的共享Wi-Fi,然後用Charles監聽微信的網絡請求(發照片或者刷朋友圈)。
如果是平臺的API,可以用成熟但是複雜的OAuth2,新浪微博這篇:授權機制說明

各端的具體實現
如上面的圖所示,Server統一提供一套RESTful API,web+ios+android作爲同等公民調用API。各端發展到現在,都有一套比較成熟的框架來幫開發者事半功倍。

-- Server --
推薦: Spring MVC 或者 Jersey 或者 Play Framework
教程:
Getting Started · Building a RESTful Web Service

-- Android --
推薦: RetroFit ( Retrofit ) 或者 Volley ( mcxiaoke/android-volley · GitHub Google官方的被block,就不貼了 ) 
教程:
Retrofit โ€” Getting Started and Create an Android Client
快速Android開發系列網絡篇之Retrofit

-- iOS --
推薦:RestKit ( RestKit/RestKit · GitHub )
教程:
Developing RESTful iOS Apps with RestKit

-- Web --
推薦隨便搞!可以用重量級的AngularJS,也可以用輕量級 Backbone + jQuery 等。
教程:blog.javachen.com/2015/

參考:
[1]: Some REST best practices
[2]: GitHub API v3
[3]: tlhunter/consumer-centric-api-design · GitHub
發佈了4 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章