Like Share Discussion Bookmark Smile

J.J. Huang   2020-02-27   Tech.   瀏覽次數:

技術觀念 | 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
    快取機制可以在ClientServer中實作。
  • 分層Layered
    在發出請求的Client與送出回應的Server之間可以有好幾個Server中間人(稱作Connectors),彼此獨立並且不會影響到 RequestResponse
  • 統一操作介面Uniform Interface
    將操作細節抽象出來,降低耦合並提高獨立性。
  • 按需代碼Code-On-Demand (可選)
    伺服器可以通過傳送可執行代碼給客戶端的方式臨時性的擴充功能或者客製化功能。例如:Java AppletFlashJavaScript

這些特性是讓REST強大的原因。

REST 元素

REST有三個主要角色:Data ElementsConnectorsComponents

  • Data Elements(數據元素)
    ResourceRepresentation是兩個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可能比較陌生,但是兩者的概念是一樣的,都是一種識別資源的方法,而URLURI的一種,有興趣暸解兩者關係的可以看這篇What is the difference between URI, URL and URN?回答。

    Resource Metadata則是儲存Source LinkAlternates等資訊。

    Representation是表示這個資源目前的狀態,Content-Type(e.g. application/html, image/jpg)就是一種RepresentationRepresentation Metadata則包含了Media TypeLast-Modified Time等資料。
  • Connectors(連接器)
    REST connectors包含五種型態:ClientServerCacheResolverTunnel。其中ClientServer是兩種主要型態。一次請求到回應的路徑是:Server監聽 → Client發出RequestServer收到 → 傳回ResponseCache的機制則可以實做在Client端或是Server端。Resolver的角色像是ClientServer的中間人(e.g. DNS lookup),Tunnel則可以做強制加密等工作。
  • Components(組件)
    REST components包含四種角色:User AgentOrigin ServerGatewayProxyUser Agent就是有時候當我們要用爬蟲,會必須要註明User-Agent = “Mozilla/5.0”的那個User Agent(此篇文章很幽默的解釋了 Mozilla/5.0 的由來。)User Agent代表瀏覽器那一方,Origin Server則代表伺服器那一方。GatewayProxy則是在User AgentOrigin 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只需要知道RepresentationAction(要對資源做的動作)就夠了。

標準化介面

REST介面有三要素:名詞(Noun)、動詞(Verb)、表徵(Content Type)。

  • Noun就是要操作的Resource,像是 https://morosedog.gitlab.io

  • Verb是一組有限的操作指令,包含GETPOSTPUTDELETE

  • Content Type是一組有限的內容格式,也就是Representation,像是HTML

所以 RESTful 是?

美麗(Beauty)的事物可以稱為Beautiful;設計為REST的系統就可以稱為RESTful

RESTful路由便是充分應用REST風格的路由設置。而你可以透過URL(Uniform Resource Locator),也就是這些資源的地址,來取得這些資源並在你的瀏覽器上使用。

線上影片講解 RESTful Services (RESTful APIs)

網路上查到很可愛的圖示說明影片

  • 將程式的狀態和功能拆解成資源Resource
  • 每個獨立的url可以對應到相對的resource
  • 而可以使用putget patch這種動作對resource操作。
  • 簡單的說就是看到網址,就可以定義出對應到的資源。
  • 搭配動作可以對應到對於該資源的處理方式。

一些常見名詞

Base-urlEndpointParameter是幾個REST API常見的名詞,先解釋一下:

  • Base-url
    一次API請求的基本盤。假設今天去餐廳外帶餐點,那base-url就是那家餐廳的外賣窗口,所有你想在這家餐廳點的菜都從這裡開始。

  • Endpoint
    請求的資源本身。同樣以去餐廳外帶做比喻,endpoint就是你要點的菜。

  • Parameters
    你的客製化選項。比如說大辣小辣、要不要付餐具、哪個日期區間的資料etc.記得,這些選項必須是API提供者有提供的,比如說你不能要求「加香菜」到你的蛋炒飯如果店家沒有這個選項。所以記得好好閱讀API文件。

其它架構方法

以前最常被用來與REST比較的架構方法是RPC,現在大概是GraphQL

GraphQL 入門: 簡介 X 範例 X 優缺點

RPC: Remote Procedure Call

RPC定義上來說是一個電腦程式(computer program)讓一個程序(procedure)在另一個記憶體位置(address space)(通常就是在另一台電腦或網路上)執行。同樣使用Client-Server interactionRPC實作上有SOAPXML-RPCRPCREST最大的不同是,在Client 與物件溝通之前,它必須先擁有這個物件的知識才能進行操作。相反地,REST則是只要知道物件的狀態就好了。多數人擁抱REST的原因是因為它簡單又很有威力,但同樣也因其簡單而讓人感到侷限。

舉例:

一個RPC應用程式可能會定義以下的操作:

1
2
3
4
5
6
7
8
9
10
11
12
getUser()
addUser()
removeUser()
updateUser()
getLocation()
addLocation()
removeLocation()
updateLocation()
listUsers()
listLocations()
findLocation()
findUser()

Client的程式碼可能會這樣存取:

1
2
exampleAppObject = new ExampleApp("example.com:8888")
exampleAppObject.getUser()

REST中,重點在resources(或稱作nouns)的多樣性,比如說可能有以下的用法:

1
2
3
4
5
6
example.com/users/
example.com/users/{user} (one for each user)
example.com/findUserForm
example.com/locations/
example.com/locations/{location} (one for each location)
example.com/findLocationForm

Client的程式碼可能這樣存取:

1
2
userResource = new Resource(http://example.com/users/001)
userResource.get()

每個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