iT邦幫忙

2024 iThome 鐵人賽

DAY 17
3
Software Development

微服務奇兵:30天Quarkus特訓營系列 第 17

後端協定基礎知識建置-認識RESTful API設計原理

  • 分享至 

  • xImage
  •  

在整個聊解完HTTP後,接著就要進入如何去定義溝通格式這件事情。目前你對於HTTP是用來做系統間的溝通,且有加密處理。那我們如何去定義實際的資料格式呢? 此篇會針對這部分去闡述介紹RESTful API規範格式。接下來的章節可能會比較複雜,我會盡量讓內容有邏輯地連貫,幫助大家理解。

REST設計風格-分散式數據交換管理問題

在進入RESTful API講解前,先提一下REST,RESTRepresentational State Transfer,代表狀態轉移)是一種設計 Web 服務指導原則設計模式。提到設計模式,代表它一定是為了解決某些常見、不統一或重複出現的問題。在以往分散式系統中數據的交換和資源管理確實具有某些問題

資源的統一訪問方式

在早期的網路服務設計中,不同系統可能會為每種操作(如查詢、更新、刪除數據)設計不同的API端點和接口,這會導致開發和維護的複雜性增加。而 REST 提供了一個統一的方法來訪問和操作資源,通過 HTTP 動詞(如 GET、POST、PUT、DELETE)簡化了資源的操作方式。

講一下具體例子,這樣後面才可以了解資源為核心這個概念,例如現在有一個用戶管理系統可能會有這樣的API端點

# 查詢用戶信息:
GET /getUserInfo?userId=abc123

# 建立新用戶:
POST /addUser

# 更新用戶信息
PUT /modifyUser?userId=abc123

# 刪除用戶
POST /removeUser?userId=abc123

這樣的API設計混用了不同的動詞和端點,隨著API規模增大,會增加維護成本。開發者需記住每個操作對應的端點名稱及其請求方式,增加了錯誤發生的機會。

REST設計風格則將操作統一到資源上(如user),並使用標準的HTTP動詞來操作:

# 查詢用戶信息:
GET /users/abc123

# 建立新用戶:
POST /users

# 更新用戶信息
PUT /users/abc123

# 刪除用戶
DELETE /users/abc123

這樣的設計簡化了API結構,統一了操作邏輯,減少了冗餘,提高了可讀性與可擴展性。

無狀態通信

在傳統系統中,伺服器需要保存客戶端的狀態(如登錄會話),這會給伺服器帶來負擔,尤其是在高併發環境中。REST則要求每次請求都應包含所有必要信息,伺服器不需記住任何過去的狀態,從而提高了系統的可擴展性。

例如,傳統系統中的用戶登錄流程可能如下:

# 用戶登入
POST /login

請求內容:{ "username": "user1", "password": "password123" }

伺服器處理後,會創建一個登錄Session並返回Session ID。後續請求需要附帶這個Session ID,讓伺服器知道用戶身份。此時伺服器需要檢查 SessionID 是否有效,並且根據這個ID來獲取用戶的狀態資訊。

# 查詢用戶資料
GET /getUserInfo

Header SessionID: abc123

在RESTful API中,登錄後伺服器不再保存Session,而是回傳一個JSON Web Token (JWT)。每次請求都附帶這個Token,伺服器只需驗證Token來識別用戶,不需保存任何會話狀態。

Token 是一種認證方式, Token 包含使用者的身份與授權資訊。客戶端在每次發送請求時,都需帶上這個 Token,伺服器會根據 Token 來驗證請求是否合法,而不需要儲存使用者的登入狀態,

簡單的資料格式與超媒體驅動(HATEOAS)

早期的網路服務,如SOAP(簡單物件存取協定),通常使用**XML(延展性標記語言)**來傳輸資料。雖然XML結構靈活且具有高度擴展性,但其格式冗長,解析過程相對複雜,開發者必須投入額外的時間學習和實作。SOAP還要求服務介面遵循嚴格的協定定義,導致學習門檻較高並增加了開發的複雜度。REST則提倡使用簡單的資料格式(如JSON),並支持跨平台的互相操作

跨平台的互通性

早期的網路服務常依賴特定技術堆疊,導致不同平台或程式語言之間的互通性差。例如,某些服務可能只能在 Java 上被使用(ex:RMI(Remote Method Invocation)) ,其他語言的系統則難以整合。

為了解決這些問題,Roy Fielding 提出了代表狀態轉移(REST)作為設計Web服務的架構方法,來解決分散式系統上述提到的問題。它算是一個設計模式(風格),強調的是資源的操作狀態轉移,不特定針對某個協議綁定。

所謂的「狀態表示」指的是伺服器在回應客戶端時,傳送的是資源的當前狀態,通常是資料庫中存儲的相關資訊。比如當客戶端請求查看一個用戶的資料,伺服器會查詢資料庫中的用戶訊息,然後返回這些訊息作為「資源的表示(呈現)」(representation)。

關鍵是這個表示只是當前的數據狀況,而不是整個資源本體。當你發出更新操作時,伺服器會將新的狀態寫入資料庫,然後把更新後的狀態回傳給你。這個過程就叫「狀態轉移」,因為每次操作都會轉移或更新資源的狀態。

REST設計風格-RESTful設計理念

在理解REST設計初衷後,接著開始進入REST的設計規範。「REST」(Representational State Transfer)加上「-ful」這個後綴。後綴「-ful」表示「充滿…的」或「具備…特性的」。所以

「RESTful」意思是「具備 REST 架構特性」

通常用來形容遵循 REST 原則的 API 或系統設計,所以才聽到有人問,你會不會寫RESTful API,意思是指會不會設計具有REST原則特性的API規範內容。那REST有哪些原則定議呢? 從字面上就可以大致表現出來,「REST」 是 Representational State Transfer 的縮寫,翻譯成中文是「表現層狀態轉移」。從這個名稱可以解讀出 REST 的核心概念,它主要是指透過**「資源的表示」來進行狀態的轉移**,並依此設計 API。

幾個重要原則如下:

  1. Representational :每個資源(例如:一個產品、一篇文章)可以用不同的格式來顯示。這些格式可以是 JSON(像是程式讀得懂的格式)、XML(有層次結構的格式)、或者 HTML(網頁上看到的格式)。當客戶端(像是你的手機 App 或網站)透過 API 發出請求時,伺服器會回傳這些資源的「表現形式」。換句話說,客戶端要的並不是直接拿到資料庫裡面的內容,而是透過這些格式化的方式來取得資源,這樣客戶端就能使用這些資料進行顯示或處理。

  2. 狀態轉移(State Transfer):當客戶端(像是你的手機 App 或瀏覽器)發出請求給伺服器時,伺服器會回傳一個當前資源的「最新狀態」。例如,你在購物網站上查詢一個商品的庫存數量,伺服器就會回傳目前的庫存狀態,這就是「狀態轉移」。

以上兩個精神延伸出的 REST 核心原則:

  • 資源導向:資源是 REST 中的設計核心,「資源」表使用者資料、產品資訊、文章內容等。每個資源都有一個唯一的URI(統一資源識別符)。如我上述提到資源的統一訪問方式的範例,圍繞在user這個資源去設計我的API。

  • 無狀態:每次客戶端(像是手機 App)發出請求時,伺服器不會記住之前的互動,所以每次請求都要包含所有必要的資訊。這樣伺服器不需要儲存使用者的歷史資料。

  • 統一接口:REST 使用標準的 HTTP 動詞來操作資源,例如

    • GET:用來讀取資料
    • POST:用來新增資料
    • PUT:用來更新資料
    • DELETE:用來刪除資料
  • 隔離系統: 在 REST 中,客戶端與伺服器之間的通信是「隔離」的,客戶端不需要了解伺服器的內部實作細節,伺服器也不必知道客戶端的處理方式。兩者可以各自獨立運作,當其中一方進行升級或改動時,另一方不會受到影響。

  • 可快取:伺服器回應的資料可以被快取,這樣下次請求相同的資源時,就不用再次向伺服器請求,提升效能。

  • HATEOAS(Hypermedia as the Engine of Application State): 伺服器回傳的資料不僅包含資源本身,還包含下一步的操作超連結,客戶端透過這些連結來發現可以進行的操作,而不必事先知道所有 API 的結構。

例如當你查詢某筆訂單時,伺服器會返回該訂單的詳細資料,並且提供後續可進行的操作鏈結,如更新訂單、取消訂單等。

{
  "orderId": 12345,
  "status": "pending",
  "totalAmount": 500,
  "_links": {
    "self": {
      "href": "/orders/12345"
    },
    "update": {
      "href": "/orders/12345/update",
      "method": "PUT"
    },
    "cancel": {
      "href": "/orders/12345/cancel",
      "method": "DELETE"
    }
  }
}

客戶端只需依據伺服器回應中的鏈結來操作,不需要事先知道怎麼更新或取消訂單。這就是HATEOAS的概念,它讓API具有自我描述的能力,使客戶端更容易操作和擴展。

上述整個看完,應該對RESTful API有很清楚的設計認知,也會清楚知道,它是協定傳輸規範的模式設計,而HTTP是我們最常被套用的協定格式。

REST設計風格-RESTful簡易範例

這裡我再稍微借用Howie Mann的圖 再次闡述一下REST API 定義 HTTP 方法與 URL 進行資源的訪問,並且以 JSON 格式交換資料。

https://ithelp.ithome.com.tw/upload/images/20240918/20115895J1VNaXUJO5.png

在這個例子中,資源項目是 調查 (survey),每個調查都有一個唯一的路徑表示,比如 /surveys 代表所有的調查,而 /surveys/123 代表特定ID(這裡是123)的調查。

HTTP 為具體行為,通常用動詞表示,而UR為我們的訪問資源路徑,例如

  • GET:從伺服器獲取資料,查詢現有的資料項目。
    • GET /surveys 就是查詢所有調查。
    • GET /surveys/123 則是查詢ID為123的調查。
  • POST:向伺服器發送新的資料,創建一個新的資料項目。
    • POST /surveys 用來新增一個新的調查。
  • PUT:更新伺服器上已經存在的資料項目,發送修改後的資料到伺服器。
    • 例如 PUT /surveys/123 是用來修改ID為123的調查。
  • DELETE:刪除伺服器上已經存在的資料項目。
    • 例如 DELETE /surveys/123 就是刪除ID為123的調查。

Json為調查回應 (survey response)數據,例如當你查詢某個調查回應時,可能會收到這樣的結果。例如**GET /surveys/123/responses/4**,查詢ID為123的調查中,ID為4的回應,伺服器回傳該回應的詳細資料。這張圖很直接表示出REST具體的操作定義狀況。

闡述完這章節,相信你對RESTful有一定的認知,下章節會具體闡述在設計過程要如何明確定義它的格式與資料。


上一篇
後端協定基礎知識建置-HTTPS 版本差異
下一篇
後端協定基礎知識建置-Google RESTful API設計
系列文
微服務奇兵:30天Quarkus特訓營30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言