天天看點

揭開 RESTful 的神秘面紗:誤解與真相

作者:CSDN

【編者按】通過一個真正的 RESTful API 的例子,即螢幕抓取,強調了 RESTful API 的核心是如何通過 HTML,HTTP 和 URLs 的結合,實作一個可以緩存、代理或負載均衡請求的分布式超媒體系統。

原文連結:https://cohost.org/tef/post/1794038-special-interest-inf

未經允許,禁止轉載!

作者 | tef 譯者 | 明明如月責編 | 夏萌

出品 | CSDN(ID:CSDNnews)

事實真相如下:

  • 對 RESTful API 的誤解
  • REST 是過去 Web 的工作方式
  • 識别 非 Rest 架構
  • 一個真正的 Restful API:網頁抓取
揭開 RESTful 的神秘面紗:誤解與真相

對 RESTful API 的誤解

那些聲稱 “這是一個 Restful API” 的人,大多數時候可能隻是在誇大其詞,完全是誤導。那些宣稱“你的産品應該是 Restful”的人,通常他們的意思是“請按照我喜歡的方式來做事”。這個“我喜歡的方式”通常是“正确地使用 HTTP”,再加入一些其他元素。 這些“其他元素”通常是一些奇特的迷信和命名規範,而在真正的 Rest 架構中,這些并不重要。

換言之,真正的 Rest 并不僅僅是關于 CRUD 操作或是暴露一個檔案系統,也并非關于 URL 的命名方案,或是選擇 PATCH 還是 POST。 實際的 REST 是關于“網絡浏覽器是如何運作的”,并且其核心思想源自一篇完全不同的論文——《通過限制來定義架構風格(defining architectural styles through constraints)》。盡管這篇論文并未對了解 Rest 的工作方式提供直接定義,但其閱讀價值仍然不言而喻。

揭開 RESTful 的神秘面紗:誤解與真相

REST 是過去 Web 的工作方式

1、REST 關注的是網頁浏覽器與網頁伺服器之間的互動用以建構一個分布式超媒體系統。

2、REST 并非隻是關于 APIs,更是關于如何将傳輸協定(如 HTTP)、接口描述(如 HTML)以及應用狀态(如 URL)有機融合。

    • 它展示了如何利用像 HTTP 這樣的協定,讓你能夠隐形地使用負載均衡器、緩存或代理。
    • 它揭示了如何利用像 HTML 這樣的接口描述,使服務在網絡上以平台中立的方式呈現接口。
    • 它關注于如何在 URL 中存儲應用狀态,通過連結和表單等方式操作 URL,而不是在用戶端或伺服器端維護狀态。
    • 它闡述了伺服器如何改變所有的 URL,隻要連結得到了更新,一切仍然能夠正常運作。
    • 它舉例了 REST 的特性:在兩個新标簽頁中打開"next",你将看到兩次相同的頁面,而非分别出現第2頁和第3頁。
    • 它意味着在網頁上點選next來進入下一頁,而不是要求使用者輸入/collection?offset=80。

    3、REST 也描述了如何使用标準方法來實作這個功能,這樣任何網頁浏覽器都可以通路并與任何網頁伺服器進行互動。

    4、換言之,REST 就是讓你能夠用自己的網頁浏覽器與網絡郵箱互動的一種方式,而浏覽器并不需要了解任何有關電子郵件的資訊。

    5、最接近 REST 的實際概念是 "理查德森成熟度模型",它将 "成為 REST" 的過程分解為三個簡單的步驟:

    • 和負載均衡器和諧共處:不同的事物具有不同的 URL。
    • 與緩存和諧共處:GET 請求可以被緩存,POST 請求則不能被緩存。
    • 與浏覽器和諧共處:真正提供 HTML。如今,畫出那隻該死的貓頭鷹。
    6、如果沒有浏覽器,就沒有 REST。但是,僅僅有一個浏覽器本身并不能讓事物符合 REST 原則。
揭開 RESTful 的神秘面紗:誤解與真相

識别非 REST 架構

1、為了充分了解網絡的運作原理,我們需要研究那些不完全符合網絡規範的案例。

2、以 Gopher 協定為例,相較于 HTTP 來說,Gopher 提供的功能存在局限性:

    • 它基于請求/響應協定
    • 中間件無法真正緩存結果,除非寫死了某些例外
    • 它具有固定的内置類型清單,而非動态的内容類型字段
    • 僅有菜單類型和目錄類型可以連結到其他檔案
    • 存在一個特别的指令:搜尋操作。任何其他特别的指令都必須通過協定擴充來實作
    • 盡管它是一種浏覽器,但并不符合 REST 原則
    • 如果網絡按照這種方式運作,為任何 Gopher 用戶端編寫電子郵件服務将會變得極其困難
    3、REST 并不等同于“檔案系統”,以 9P 協定為例:
    • 9P 是一種遠端檔案系統協定,但它使用檔案描述符而非傳遞檔案名
    • 用戶端進行身份驗證,并打開指定路徑作為會話的根目錄
    • 用戶端可以對目錄的檔案描述符進行 walk 操作以擷取檔案清單
    • 在協定的意義上,隻有目錄可以連結到其他檔案
    • 檔案沒有類型化,全部都隻是資料塊(blob)
    4、即使 9P 可以浏覽檔案系統,也不能像網絡那樣:
    • 它沒有特殊的指令:所有事情都必須通過檔案操作來實作,例如,将 "now" 回顯到 /service/next_reboot
    • 缺乏超媒體,但有一些相似的習慣用法。一個 Plan9 服務會暴露一些檔案,其中有一個檔案名,如 /net/mux 傳回 1,是以用戶端決定從 /net/1/ctl 讀取
    • 雖然任何 9P 用戶端都可以連接配接到任何 9P 服務,但一個服務提供的其他功能與另一個服務之間可能存在很大差異
    • 你可以在檔案系統上提供電子郵件服務,但最終還是需要在其上編寫一個電子郵件用戶端,這幾乎等同于一個浏覽器插件。
    • 值得注意的是,對于 Plan9 的 9P,編寫中間件(如代理、緩存或負載均衡器)并不簡單,因為必須跟蹤檔案描述符如何比對檔案
    • 然而,即使使其更像 HTTP 也不夠
    5、網絡不僅僅是“通過 HTTP 提供的檔案系統服務”
    • 确實,你可以獲得緩存、負載均衡器和代理,但這隻是開始
    • 一個大問題是:超媒體在哪裡,應用狀态的引擎是什麼?
    • 使用 WebDAV 服務時,用戶端必須知道具體的 URL 位址,而在網絡上,通常是通過連結名稱通路資源,而不是直接使用 URL 位址通路
    • 任何特殊操作仍然需要通過讀取或寫入檔案的形式實作,每個基于它建構的應用程式可能會有不太相同的功能
    • 相比之下,一個網絡會話可以在 URL 内從一個請求攜帶狀态到下一個,因為用戶端通過名稱導航
    6、通常來說,通過 HTTP 的 JSON-RPC 并不完全符合 REST 原則:
    • 使用 HTTP 可以輕松獲得緩存、負載均衡和代理,你的 API 并不需要像檔案系統那樣才能從中間件中受益,但關于 REST 的部分就這些了
    • 有時有一些狀态傳遞,就像 Plan9 傳回檔案名那樣
    • 如果你有一個分頁 API,它涉及将一個令牌從一個回複傳到下一個請求,那麼你就很接近使用 URL 來模組化應用狀态
    • 問題是什麼?他們使用的是模式,而不是 HTML,這個模式必須提前下載下傳
    • 用戶端不能像從 HTML 中讀取一樣從模式中讀取
    • 如果一個網頁浏覽器以同樣的方式工作,你将為每個網站下載下傳電子應用程式
    7、對于以上的内容,我們總結如下:
    • REST 是關于如何将 HTML、HTTP 和 URL 結合起來形成一個分布式超媒體系統
    • 它描述的系統可以在不需要新的用戶端代碼的情況下進行請求的緩存、代理或負載均衡。
    • 它涉及的系統會将應用狀态編碼在 URL 中
    • 它涉及的系統可以通過點選連結或表單來更改應用狀态

經過以上的分析,你可能會問,為什麼有人會想制作一個 RESTful API?你甚至可能會問,一個真正的 RESTful API 究竟是什麼?答案是,RESTful API 确實存在,它們看起來就像一個網頁浏覽器。

揭開 RESTful 的神秘面紗:誤解與真相

深入了解真正的 RESTful API:從螢幕抓取說起

  • 下面的代碼展示了一個真正的 RESTful 用戶端應該實作的方式:
import browser                  api = browser.Open("http://localhost:1729/service")                  users = api.Click("admin").Click("users")                  result = users.Submit("create", {"name": "jeff"})                  if result.Error is not None:              # etc           

是的,這是一個螢幕抓取的例子。真正的 RESTful API 可以被看做一種螢幕抓取:

  • 它使用 HTTP,是以滿足了緩存、負載均衡器、代理的需求。
  • 在理論上,API 可以支援 JavaScript, 是以按需加載代碼并不是必須的。
  • 并且,因為連結和表單都在 HTML 中,任何的改變都會自動生效。
  • 我知道這聽起來瘋狂,但這正是 Roy Fielding 教授想要的結果。
  • 對于那些“建構應用程式的應用程式”,他希望它們的工作方式能夠像一個 Web 浏覽器一樣。

如果你的 API 和這個定義不相符,那麼就很可能不是 RESTful。

理論上,它可以使用除 HTML 以外的其他語言,但是替代 HTML 的語言必須足夠通用,以描述不同類型的接口。有時候,人們聲稱他們已經建立了一個 RESTful 系統,但是每個接口都是獨特的資源類型,而不是使用統一的語言(如 HTML)來描述每個接口。

在真正的 RESTful 架構中,你可以使用同一個用戶端來通路多個不同的服務,而且可以在不需要明确要求用戶端的情況下将狀态從一個請求傳遞到另一個請求。

也許最吸引人的一點是,通過使用 HTML,REST 可以以一種與現有中間件和服務進行互操作的方式表示比 HTTP 更豐富的操作集,而用戶端不需要事先了解和預先知道每個接口的具體資訊。‍‍

你是否也曾對某個概念産生過誤解,是否也曾在某一刻恍然大悟?