RESTful架構
一、概述:
-
RESTful架構,就是目前最流行的一種互聯網軟件架構。REST是Representational State Transfer詞組的簡寫,即“表現層狀態轉化”。代表(互聯網資源)表現層狀態轉化。
-
REST是Roy Fielding博士在2000年在其論文中第一個提到的,因爲他是互聯網行業內一個重要的人物(HTTP 1.0/1.1協議的主要設計者、Apache開源基金會的第一任主席),所以引起了人們的關注,並且對互聯網產生了深遠的影響。
-
RESTful不是一個標準,但是一種規範。現在很多軟件使用使用前後端分離的應用結構,它結構清晰、符合標準、易於理解、擴展方便。前端(H5、Android、iPhone、小程序)往往通過調用API的方式與後端進行數據交換。那麼,符合RESTful規範的軟件架構的API我們可稱之爲RESTful APl。如微博開放API和Github開放API就嚴格遵循了RESTful規範。
以上是對RESTful架構的概述,在本文中,我將使用自己的理解完整的表述RESTful的規範,以及如何設計符合RESTful規範的API。實際上,在對計算機技術的理解中,一百個人可能會有一百種理解方式,儘管見仁見智,但我們的目的都是把技術當作工具,去實現我們的程序功能。如果在本文中的描述有所錯誤,或您有所不解,歡迎留言評論!
下面將分爲將分爲三個內容,展開描述我對RESTful的理解:
1.理解 RESTful
2.RESTful API架構規範
3.RESTful API 設計示例
二、理解RESTful
要理解RESTful,我們需要從每一個詞開始理解。Roy Fielding將他對互聯網軟件的架構原則命名爲REST,即Representational State Transfer的縮寫,代表(資源)表現層狀態轉化。如果一個軟件架構符合REST原則,就稱它爲RESTful架構。
1. 資源(Resources)
我們在互聯網軟件開發中,我們所說的“資源”是指在互聯網中某一個節點的具體信息,如一段文本、一張圖片、一個視頻、一個壓縮包、一個程序安裝包等等。在互聯網中,我們可以使用URI(統一資源定位符)來表示每一個具體的資源,因此,每一個互聯網資源都一個獨一無二的URI地址。
2. 表現層(Representational)
“資源”是一種信息的實體,實際上,資源有很多表現形成,如一段文本,我們可以使用普通的txt格式來表示,也可以用JSON格式來表示,還可以使用XML格式來表示。“資源”的具體表現形式我們就叫做表現層。在HTTP協議中,規定了頭信息中的Content-Type字段來描述具體的資源表現形式。如“Content-Type: text/html”表示爲html格式的文本數據,而“Content-Type: text/json”表示爲JSON格式的文本數據。
1. 狀態轉化(State Transfer)
HTTP是一種無狀態的網絡協議,如果客戶端要操作服務器,必須通過一種手段通知服務器進行“狀態轉化”,而這種狀態改變建立在“表現層”之上,這就是“表現層狀態轉化”。在HTTP協議中,客戶端通過發送相應的請求告知服務器實現某種狀態的改變。客戶端使用GET、POST、PUT、DELETE4個表示操作方式的動詞對服務端資源進行操作。
綜上所述,我們可以總結一下RESTful的特點:
a. 每個互聯網資源都有一個唯一的URI地址;
b. 通過操作資源的表現形式來操作資源;
c. 一般情況下使用JSON格式來表示具體的數據;
c. 使用HTTP協議進行客戶端與服務端之間的交互,從客戶端到服務端的每個請求都必須包含理解請求所必需的信息;
d. 客戶端使用GET、POST、PUT、DELETE 4個表示操作方式的動詞對服務端資源進行“狀態”操作。
三、RESTful API架構規範
REST並沒有明確的設計標準,可以說RESTful是一種設計風格的規範化。在RESTful API設計中,不同的組織可能還存在不同的設計風格規範,但是整體上RESTful的風格規範是一致的。
也正是因爲有了一致的風格規範,讓讀API的人更好地理解API,甚至不用閱讀文檔,就知道API要實現的某個資源的某種“狀態轉化”。根據Github開放API或者微博開放API的設計風格。下面是我總結的RESTful API的相關風格規範,今後我將使用此規範進行API開發。
1. 協議
客戶端與服務器之間使用HTTP或者HTTPS協議進行通信。
2.域名
應當儘量將API程序部署到專有的域名之下,如:
https://api.demo.com
如果API比較簡單,或者不考慮進行擴展,應當放在項目的子模塊中,如:
https://demo.com/api/
3.API版本
應當將API版本放在URL中,如微博開放API就將版本號放在URL中:
http://api.weibo.com/2/
如果我們把版本號理解成資源的不同表述形式的話,API版本應放在HTTP請求頭Accept字段中,如github中的開放API
Accept: application/vnd.github.v3
可能github考慮很多因素,所以把請求的API版本放到HTTP請求頭裏了。實際上,如果我們想要快速的開發一個API程序,使用第一種形式會更加直觀與方便。
4.路徑
對於不同的資源,都有一個唯一的URL地址,每一個URL地址代表一種資源,所以網址中應當是名稱,不能是動詞,而且名詞應當與數據庫表名對應。一般來說,數據庫中保存的是數據集合,所以URL中對應的資源應當是名詞複數。
如Github開放API中,列出一個組織的項目集合:
https://api.github.com/orgs/:org/projects
在上面URL中,orgs代表組織集合,而:org代表集體的組織名,projects代表具體的資源
5.HTTP動詞
對於資源的某種具體操作類型,需要客戶端發送不同的HTTP動作來完成。
常用的五個HTTP動詞已經對應操作如下:
* GET(Retrieve):從服務器取出資源(一項或多項);
* POST(CREATE):在服務器新建一個資源;
* PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源);
* PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性);
* DELETE(DELETE):從服務器刪除資源。
實際上,最常用的額HTTP動詞原先只有4個,即GET、POST、PUT、DELETE,PATCH方法是新引入的,是對PUT方法的補充,用來對已知資源進行局部更新。
有時候,只需要修改一個屬性,開發者通常(爲圖省事)把一個包含了修改後完整信息傳給後端,做完整更新。但實際上如果需要考慮性能優化,是有必要做局部更新的。
6.過濾
在獲取服務器資源的時候,大部分情況是需要進行過濾的,而不是獲取數據庫中的完整集合。這時候需要設置過濾條件,我們可以將過濾條件作爲參數拼接到URL中。如下:
?limit=10 # 指定獲取10條信息集合
?page=1&limit=10 # 指定每頁10條信息,獲取第1頁信息集合
?limit=10&deleted=true # 獲取數據庫中已經標誌爲刪除的10條信息集合
7.返回
使用相應的HTTP狀態碼,將結果告知客戶端,以下是常用的HTTP狀態碼以及狀態描述:
狀態碼 | 描述 | 備註 |
---|---|---|
200 | OK - 成功 | |
204 | NO CONTENT - 無內容 | DELETE返回204狀態碼,表示資源已經不存在 |
303 | See Other - 其他 | 表示參考另一個 URL,此時應當返回URL鏈接 |
400 | bad request - 服務器不理解客戶端的請求(如,參數錯誤) | |
401 | Unauthorized - 沒有通過身份驗證 | |
403 | Forbidden - 沒有訪問權限 | |
404 | Not Found - 資源不存在,或不可用 | |
405 | Method Not Allowed - 對於此HTTP方法沒有權限 | |
409 | conflict - 通用衝突 | 如被請求的資源與其當前狀態之間存在衝突,請求無法完成 |
410 | Gone - 資源不存在,或不可用 | |
415 | unsupported media type - 不支持的媒體類型 | 如服務器需要客戶端使用JSON數據請求,而客戶端使用XML進行請求 |
429 | Too Many Requests - 請求次數超過限額 | |
500 | internal server error - 服務器通用錯誤 | 如果客戶端請求有效,服務器處理時發生了意外 |
503 | Service Unavailable - 服務端當前無法處理請求 | 如網站正在維護,服務器無法處理請求 |
- 正常:如果正常返回數據,應當使用msg或者其他關鍵字作爲鍵名返回給客戶端,如下:
{
"data":[
"user_id":1,
"name":"張三",
"token":"csdcnsdvndsijudsao",
],
"message":"OK",
"code":200
}
- 錯誤:如果發生錯誤,應當使用error作爲錯誤信息的鍵名返回給客戶端
{
"error":"Unauthorized",
"code":401
}
針對不同操作,服務器向用戶返回的結果應該符合以下規範:
GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔
8.Hypermedia API
RESTful API最好做到Hypermedia,即超媒體,在返回結果中提供鏈接,連向其他API方法或者一些文檔,使得用戶不查文檔,也知道下一步應該做什麼。如Github就做到了Hypermedia,使用GET方式請求 https://api.github.com ,會返回一系列的鏈接地點:
{
"current_user_url": "https://api.github.com/user",
"current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
"authorizations_url": "https://api.github.com/authorizations",
"code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
"commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}",
.....
四、RESTful API設計示例
RESTful API風格主要體現在URL中,接下來,我們通過一個示例,來完成RESful API的URL制定。假設我們要開發一個簡單的博客系統,要給H5、Android、iPhone、小程序提供一套統一的接口。那麼預設功能與對應URL已經請求方式如下:
模塊 | 功能 | URL | HTTP請求方式 |
---|---|---|---|
用戶 | 用戶註冊 | http://api.demo.com/1.0/users/register | POST |
用戶 | 用戶登錄 | http://api.demo.com/1.0/users/login | POST |
文章 | 發表文章 | http://api.demo.com/1.0/articles | POST |
文章 | 查看文章 | http://api.demo.com/1.0/articles/:id | GET |
文章 | 修改文章 | http://api.demo.com/1.0/articles/:id | PUT |
文章 | 刪除文章 | http://api.demo.com/1.0/aritcles/:id | DELETE |
到此結束。
本文爲作者原創文章,禁止轉載,原作者:https://phy.xyz