技術觀念 | REST & RESTful 是什麼?
REST 定義
REST
(REpresentational State Transfer
)是一種網頁服務架構(Web Service Architecture
)方法,提供電腦系統一種標準化溝通的管道。
聽起來有點抽象。直接舉例:HTTP
就是一個符合REST
架構的實作。但是要記得,REST
是一種風格(並非標準),所以應用程式使用了HTTP
連線不保證它就是REST
架構。
REST
雖然是個來自WWW
的架構概念(比WWW
晚),但是這兩者並不是綁在一起,有可能設計一個大型軟體系統符合REST
但是不用HTTP
協定也不需跟WWW
互動,也有可能設計一個簡單的XML+HTTP
界面使用RPC model
而不符合REST principles
。
REST 特色
符合REST
原則的系統就是RESTful
(或是REST-compliant
)。
RESTful systems
有五個主要特性/限制:伺服器/客戶端分離、無狀態、可快取、分層、統一操作介面;一個可選的特性:按需代碼
- 伺服器/客戶端分離
Separation of Server and Client
遵照REST
設計的系統可以做到伺服器端與客戶端的實作獨立,兩者可以各自發展、互不影響,也就是說不管客戶端的程式碼再怎麼改變都不會影響到伺服器的運作,反之亦然。這是因為兩者遵循著一個溝通的格式,只要客戶端不改變傳訊息給伺服器端的方式,伺服器端也不改變傳訊息給客戶端的方式,就可以做到seperation of concerns
。
- 無狀態
Stateless
每個請求都是獨立的、自成一個個體,與前後請求無關。如此好處有很多,包含可靠(容易從錯誤中復原)、高效能與可擴充性(可以將請求交給不同伺服器處理),而元件可以被修改、更動而不會影響到系統整體的運作。
- 可快取
Cacheable
快取機制可以在Client
或Server
中實作。
- 分層
Layered
在發出請求的Client
與送出回應的Server
之間可以有好幾個Server
中間人(稱作Connectors
),彼此獨立並且不會影響到Request
與Response
。
- 統一操作介面
Uniform Interface
將操作細節抽象出來,降低耦合並提高獨立性。
- 按需代碼
Code-On-Demand
(可選)
伺服器可以通過傳送可執行代碼給客戶端的方式臨時性的擴充功能或者客製化功能。例如:Java Applet
、Flash
或JavaScript
。
這些特性是讓REST
強大的原因。
REST 元素
REST
有三個主要角色:Data Elements
、Connectors
、Components
。
- Data Elements(資料元素)
Resource
與Representation
是兩個Data Elements
中比較重要的元素。
我們可以把Resource
想像成一個物件的高級說法。若是熟悉物件導向程式設計(Object-Oriented Programming
),Resource
的概念也可以用OOP
中的物件來聯想。它有自己的類型、關聯的資料、可以被我們存取與傳送。
每個Resource
有自己的Resource Identifier
(資源標識符)與Resource Metadata
(資源元資料)。Resource Identifier
是什麼?在前面加個Uniform
,再看看它的縮寫—沒錯!就是URI
(Uniform Resource Identifier
)。雖然我們比較常聽到的是URL
(Uniform Resource Locator
),URI
可能比較陌生,但是兩者的概念是一樣的,都是一種識別資源的方法,而URL
是URI
的一種,有興趣暸解兩者關係的可以看這篇What is the difference between URI, URL and URN?回答。Resource Metadata
則是儲存Source Link
、Alternates
等資訊。Representation
是表示這個資源目前的狀態,Content-Type
(e.g. application/html, image/jpg
)就是一種Representation
。Representation Metadata
則包含了Media Type
、Last-Modified Time
等資料。
- Connectors(連接器)
REST connectors
包含五種型態:Client
、Server
、Cache
、Resolver
、Tunnel
。其中Client
與Server
是兩種主要型態。一次請求到回應的路徑是:Server
監聽 →Client
發出Request
→Server
收到 → 傳回Response
。Cache
的機制則可以實做在Client
端或是Server
端。Resolver
的角色像是Client
與Server
的中間人(e.g. DNS lookup
),Tunnel
則可以做強制加密等工作。
- Components(組件)
REST components
包含四種角色:User Agent
、Origin Server
、Gateway
、Proxy
。User Agent
就是有時候當我們要用爬蟲,會必須要註明User-Agent = “Mozilla/5.0”
的那個User Agent
(此篇文章很幽默的解釋了 Mozilla/5.0 的由來。)User Agent
代表瀏覽器那一方,Origin Server
則代表伺服器那一方。Gateway
與Proxy
則是在User Agent
與Origin Server
的溝通過程中確保效率與安全性。
三個角色間的互動
請求流向:
User-Agent (component) → (requests a representation of a resource’s state)→ Client (connector) → Server (connector) → Origin Server (component) → (sends back the response) → … → User-Agent
Components
使用Connectors
,透過一個標準化介面來操作Data Elements
。中間可以穿插任意數量的
Connectors
,但是每一層都是獨立的。Data Elements
的操作不會從Resource
本身,而是Representation
(the Representational part in REST
)(e.g. HTML, XML, JPG
)。Applications
只需要知道Representation
與Action
(要對資源做的動作)就夠了。
標準化介面
REST
介面有三要素:名詞(Noun
)、動詞(Verb
)、表徵(Content Type
)。
Noun
就是要操作的Resource
,像是 https://morosedog.gitlab.io 。Verb
是一組有限的操作指令,包含GET
、POST
、PUT
、DELETE
。Content Type
是一組有限的內容格式,也就是Representation
,像是HTML
。
所以 RESTful 是?
美麗(Beauty
)的事物可以稱為Beautiful
;設計為REST
的系統就可以稱為RESTful
。
RESTful
路由便是充分應用REST
風格的路由設置。而你可以透過URL
(Uniform Resource Locator
),也就是這些資源的地址,來取得這些資源並在你的瀏覽器上使用。
線上影片講解 RESTful Services (RESTful APIs)
網路上查到很可愛的圖示說明影片
- 將程式的狀態和功能拆解成資源
Resource
。 - 每個獨立的
url
可以對應到相對的resource
。 - 而可以使用
put
、get patch
這種動作對resource
操作。 - 簡單的說就是看到網址,就可以定義出對應到的資源。
- 搭配動作可以對應到對於該資源的處理方式。
一些常見名詞
Base-url
、Endpoint
、Parameter
是幾個REST API
常見的名詞,先解釋一下:
Base-url
:
一次API
請求的基本盤。假設今天去餐廳外帶餐點,那base-url
就是那家餐廳的外賣窗口,所有你想在這家餐廳點的菜都從這裡開始。Endpoint
:
請求的資源本身。同樣以去餐廳外帶做比喻,endpoint
就是你要點的菜。Parameters
:
你的客製化選項。比如說大辣小辣、要不要付餐具、哪個日期區間的資料etc.
記得,這些選項必須是API
提供者有提供的,比如說你不能要求「加香菜」到你的蛋炒飯如果店家沒有這個選項。所以記得好好閱讀API
文件。
其它架構方法
以前最常被用來與REST
比較的架構方法是RPC
,現在大概是GraphQL
。
RPC: Remote Procedure Call
RPC
定義上來說是一個電腦程式(computer program
)讓一個程序(procedure
)在另一個記憶體位置(address space
)(通常就是在另一台電腦或網路上)執行。同樣使用Client-Server interaction
。RPC
實作上有SOAP
與XML-RPC
。RPC
與REST
最大的不同是,在Client
與物件溝通之前,它必須先擁有這個物件的知識才能進行操作。相反地,REST
則是只要知道物件的狀態就好了。多數人擁抱REST
的原因是因為它簡單又很有威力,但同樣也因其簡單而讓人感到侷限。
舉例:
一個RPC
應用程式可能會定義以下的操作:
1 | getUser() |
Client
的程式碼可能會這樣存取:
1 | exampleAppObject = new ExampleApp("example.com:8888") |
在REST
中,重點在resources
(或稱作nouns
)的多樣性,比如說可能有以下的用法:
1 | example.com/users/ |
Client
的程式碼可能這樣存取:
1 | userResource = new Resource(http://example.com/users/001) |
每個resource
擁有自己的識別名詞,而Clients
從單一resource
開始瀏覽,透過標準操作走訪resource
,如GET
下載,PUT
更新,DELETE
刪除,POST
新增,注意到每個物件有自己的URL
,而且可以容易被快取,複製跟書籤化(bookmarked
)。
註:以上參考了
REST 到底是什麼
REST服务和RESTful API是什么
淺談 REST 軟體架構風格 (Part.I) - 從了解 REST 到設計 RESTful!
什麼是 REST、RESTful 以及 RESTful Web API
什麼是 REST? RESTful?
什麼是REST跟RESTful?
百度百科-RESTful