RESTful API
一種軟件架構(gòu)風(fēng)格、設(shè)計風(fēng)格、而不是標(biāo)準(zhǔn),只是提供了一組設(shè)計原則和約束條件。它主要用戶客戶端和服務(wù)器交互類的軟件。基于這個風(fēng)格設(shè)計的軟件可以更簡潔,更有層次,更易于實現(xiàn)緩存機(jī)制等。
REST全程是Representational State Transfer,表征性狀態(tài)轉(zhuǎn)移。首次在2000年Roy Thomas Fielding的博士論文中出現(xiàn),F(xiàn)ielding是一個非常重要的人,他是HTTP協(xié)議(1.0版和1.1版)的主要設(shè)計者,Apache服務(wù)器軟件的作者之一,Apache基金會的第一任主席。所以,他的這篇論文一經(jīng)發(fā)表,就引起了廣泛的關(guān)注。
論文:
本文研究計算機(jī)科學(xué)兩大前沿----軟件和網(wǎng)絡(luò)----的交叉點(diǎn)。長期以來,軟件研究主要關(guān)注軟件設(shè)計的分類、設(shè)計方法的演化,很少客觀地評估不同的設(shè)計選擇對系統(tǒng)行為的影響。而相反地,網(wǎng)絡(luò)研究主要關(guān)注系統(tǒng)之間通信行為的細(xì)節(jié)、如何改進(jìn)特定通信機(jī)制的表現(xiàn),常常忽視了一個事實,那就是改變應(yīng)用程序的互動風(fēng)格比改變互動協(xié)議,對整體表現(xiàn)有更大的影響。我這篇文章的寫作目的,就是想在符合架構(gòu)原理的前提下,理解和評估以網(wǎng)絡(luò)為基礎(chǔ)的應(yīng)用軟件的架構(gòu)設(shè)計,得到一個功能強(qiáng)、性能好、適宜通信的架構(gòu)。
(This dissertation explores a junction on the frontiers of two research disciplines in computer science: software and networking. Software research has long been concerned with the categorization of software designs and the development of design methodologies, but has rarely been able to objectively evaluate the impact of various design choices on system behavior. Networking research, in contrast, is focused on the details of generic communication behavior between systems and improving the performance of particular communication techniques, often ignoring the fact that changing the interaction style of an application can have more impact on performance than the communication protocols used for that interaction. My work is motivated by the desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture. )
其實在REST架構(gòu)推出的十幾年間,它并沒有一路高歌的發(fā)展,真正的大范圍推廣是在2013年之后,伴隨著移動端的飛速發(fā)展,越來越多人的開始意識到,網(wǎng)站即軟件,而且是一種新型的軟件。
這種"互聯(lián)網(wǎng)軟件采用"客戶端/服務(wù)器"模式,也就是我們常說的C/S模式,這一切建立在分布式體系上,通過互聯(lián)網(wǎng)通信,具有高延時,高并發(fā)等特點(diǎn)。
網(wǎng)站開發(fā),完全采用軟件開發(fā)開發(fā)的模式。但傳統(tǒng)上,軟件和網(wǎng)絡(luò)是兩個不同的領(lǐng)域,很少有交集,軟件開發(fā)主要針對單機(jī)環(huán)境,網(wǎng)絡(luò)則主要研究系統(tǒng)之間的通信。我們需要考慮的是如何開發(fā)在互聯(lián)網(wǎng)環(huán)境中使用軟件。
要理解RESTful架構(gòu),最好的就是去理解它的單詞 Representational State Transfer 到底是什么意思,它的每一個詞到底要表達(dá)什么。
REST的釋義,"表現(xiàn)層狀態(tài)轉(zhuǎn)化",其實這省略了主語?!氨憩F(xiàn)層”其實指的是“資源(Resource)”的“表現(xiàn)層”。
所謂“資源”,就是網(wǎng)絡(luò)上的一個實體,或者說是網(wǎng)絡(luò)上的一個具體信息。它可以是一段文本,一張圖片,一首歌曲,一種服務(wù),總之就是一個具體的實例。你可以使用一個URI(統(tǒng)一資源定位符)指向它,每種資源對應(yīng)一個特定的URI。要獲取這個資源,訪問它的URI就可以了,因此URI就成了每一個資源的地址或獨(dú)一無二的識別符。所謂“上網(wǎng)”就是與互聯(lián)網(wǎng)上一系列的“資源”互動,調(diào)用它們的URI。
“資源”是一種信息實體,它可以有多種外在表現(xiàn)形式。我們把“資源”具體呈現(xiàn)出來的形式,叫做它的”表現(xiàn)層“(Representation)。
URI只代表資源的實體,不代表它的形式。嚴(yán)格地說,有些網(wǎng)站最后的”.html“后綴名是不必要的,因為這個后綴表示格式,屬于”表現(xiàn)層“范疇,而URI應(yīng)該只代表”資源“的位置。它的具體表現(xiàn)形式,應(yīng)該在HTTP請求頭的信息中使用Accept和Content-Type字段指定。
狀態(tài)轉(zhuǎn)換(State Transfer)
訪問一個網(wǎng)站,就代表客戶端和服務(wù)端的一個互動過程。在這個過程中,勢必涉及到數(shù)據(jù)和狀態(tài)的變化。
互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個無狀態(tài)協(xié)議。這意味著,所有的狀態(tài)都保存在服務(wù)端。因此,如果客戶端想要操作服務(wù)器,就必須通過某種手段,讓服務(wù)器端發(fā)生”狀態(tài)轉(zhuǎn)換(State Transfer)“。而這種轉(zhuǎn)換是建立在表現(xiàn)層之上的,所以就是”表現(xiàn)層狀態(tài)轉(zhuǎn)化“。
客戶端用到的手段,只能是HTTP協(xié)議。具體來說,就是HTTP協(xié)議中,四個表示操作方式的動詞:GET,POST,PUT,DELETE。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可用于更新資源),PUT用來更新資源,DELETE用來刪除資源
每一個URI代表一種資源
客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層
客戶端通過四個HTTP動詞,對服務(wù)端資源進(jìn)行操作,實現(xiàn)”表現(xiàn)層狀態(tài)轉(zhuǎn)換“
API與用戶的通信協(xié)議,通常使用HTTP(S)協(xié)議。
應(yīng)該盡量將API部署在專用域名之下。
http://api.rock.com
如果確定API很簡單,不會有大規(guī)模擴(kuò)充,可以考慮放在主域名之下。
http://www.rock.com/api/
應(yīng)該將API的版本號放入URL。
http://api.rock.com/v1/
也有做法是將版本號放在HTTP的頭信息中,但不如放在URL中方便和直觀。GITHUB是這么搞的。
路徑又稱”終點(diǎn)“(endpoint),表示API的具體網(wǎng)址。
在RESTful架構(gòu)中,每個網(wǎng)址代表一種資源(Resource),所以網(wǎng)址中不能有動詞,只能有名詞,而且所用的名詞往往與數(shù)據(jù)庫的表格名對應(yīng)。一般來說,數(shù)據(jù)庫中的表都是同種記錄的”集合“(collection),所以API中的名詞也應(yīng)該使用復(fù)數(shù)。
對于資源的具體操作類型,由HTTP動詞表示。
HTTP常用動詞
GET(SELECT):從服務(wù)器取出資源
POST(CREATE or UPDATE):在服務(wù)器創(chuàng)建資源或更新資源
PUT(UPDATE):在服務(wù)器更新資源(客戶端提供改變后的完整資源)
PATCH(UPDATE):在服務(wù)器更新資源(客戶端提供改變的屬性)
DELETE(DELETE):從服務(wù)器刪除資源
HEAD:獲取資源的元數(shù)據(jù)
OPTIONS:獲取信息,關(guān)于資源的哪些屬性是客戶端可以改變的、
示例
GET /students:獲取所有學(xué)生
POST /students:新建學(xué)生
GET /students/id:獲取某一個學(xué)生
PUT /students/id :更新某個學(xué)生的信息(需要提供學(xué)生的全部信息)
PATCH /students/id:更新某個學(xué)生的信息(需要提供學(xué)生變更部分信息)
DELETE /students/id:刪除某個學(xué)生
如果記錄數(shù)量過多,服務(wù)器不可能將它們返回給用戶。API應(yīng)該提供參數(shù),過濾返回結(jié)果。
?limit=10
?offset=10
?page=2&per_page=20
?sortby=name&order=desc
?student_id=id
參數(shù)的設(shè)計允許存在冗余,即允許API路徑和URL參數(shù)偶爾有重復(fù),比如 GET /students/id 和 ?student_id=id
服務(wù)器向用戶返回的狀態(tài)碼和提示信息,常見的有以下一些地方
200 OK - [GET]:服務(wù)器成功返回用戶請求的數(shù)據(jù)
201 CREATED -[POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功
202 Accepted - [*] :表示一個請求已經(jīng)進(jìn)入后臺排隊(異步任務(wù))
204 NO CONTENT - [DELETE]:表示數(shù)據(jù)刪除成功
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請求有錯誤
401 Unauthorized - [*] :表示用戶沒有權(quán)限(令牌,用戶名,密碼錯誤)
403 Forbidden - [*]:表示用戶得到授權(quán),但是訪問是被禁止的
404 NOT FOUND - [*]:用戶發(fā)出的請求針對的是不存在的記錄
406 Not Acceptable - [*]:用戶請求格式不可得
410 Gone - [GET] :用戶請求的資源被永久移除,且不會再得到的
422 Unprocesable entity -[POST/PUT/PATCH]:當(dāng)創(chuàng)建一個對象時,發(fā)生一個驗證錯誤
500 INTERNAL SERVER EROR - [*] :服務(wù)器內(nèi)部發(fā)生錯誤
如果狀態(tài)碼是4xx,就應(yīng)該向用戶返回出錯信息。一般來說,返回的信息中將error做為鍵名
針對不同操作,服務(wù)器想用戶返回的結(jié)果應(yīng)該符合以下規(guī)范
GET /collection:返回資源對象的列表(數(shù)組,集合)
GET /collection/id:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/id:返回完整的資源對象
PATCH /collection/id:返回完整的資源對象
DELETE /collection/id:返回一個空文檔
RESTful API最好做到Hypermedia,即返回結(jié)果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應(yīng)該做什么。
{
? ? "link": {
? ? ? ? "rel":? "collection https://www.rock.com/zoostudents",
? ? ? ? "href":? "https://api.rock.com/students",
? ? ? ? "title": "List of students",
? ? ? ? "type":? "application/vnd.yourformat+json"
? ? ? }
}
rel:表示這個API與當(dāng)前網(wǎng)址的關(guān)系
href:表示API的路徑
title:表示API的標(biāo)題
type:表示返回的類型
服務(wù)器返回的數(shù)據(jù)格式,應(yīng)該盡量使用JSON
API的身份認(rèn)證應(yīng)該使用OAuth2.0框架
--------------------------------------------------------------分割線-----------------------------------------------------------
Flask-RESTful
https://flask-restful.readthedocs.io/en/latest/
安裝
# pip 安裝
pip install flask-restful
# 源碼安裝
git clone https://github.com/flask-restful/flask-restful.git
python setup.py develop
創(chuàng)建Resource實現(xiàn)類
class HelloRESTful(Resource):
? ? def get(self):
? ? ? ? return {"data":"HelloREST"}
創(chuàng)建API對象,并注冊路由
# ① 創(chuàng)建并初始化
api = API(app)
# ② 創(chuàng)建,之后初始化
api = API()
api.init_app(app)
# 注冊路由
api.add_resource(HelloRESTFul,"/")