超媒體 API 與資料 API

Carson Gross

一個超媒體 API 是一個回傳超媒體的 API,通常是透過 HTTP 回傳 HTML。這種風格的 API 與不回傳超媒體的資料 API 有所區別。當今最常見的後者風格 API 形式是無處不在的 JSON API。

這兩種不同類型的 API 有著截然不同的設計需求,因此在建立時應採用不同的設計限制和不同的目標。

超媒體 API

另一方面,資料 API

#現今的 API

如今,API 通常以 JSON over HTTP 的形式來思考。這些幾乎總是面向資料的 API,而不是超媒體 API,儘管偶爾也會將超媒體概念納入其中(通常對最終用戶沒有什麼好處)。隨著業界開始意識到將資料 API 放入 RESTful 模型的問題,已經出現了遠離 RESTful API 的趨勢。

這是一件好事:業界應該在資料 API 的世界中質疑 RESTful 的概念,並開始研究更擅長服務於特定網路架構的舊客戶端-伺服器技術,將 REST 留給它被創造出來描述的網路架構:超媒體 API。

#設計一個超媒體 API

為了說明如何以不同於資料 API 的方式設計超媒體 API,讓我們考慮以下最近在 htmx discord 上出現的情況

我想要一個頁面,其中包含一個表單和一個表格。該表單將向表格添加新元素,並且該表格也將每 30 秒輪詢一次,以便顯示來自其他用戶的更新。

讓我們從基本 URL /contacts 的角度來考慮這個 UI

我們需要的第一件事是一個端點來檢索表單和當前聯絡人的表格。這將位於 /contacts,結果如下

  GET /contacts -> render the form & contacts table

接下來,我們希望能夠建立聯絡人。這將透過向同一 URL 發送 POST 請求來完成

  GET /contacts -> render the form & contacts table
  POST /contacts -> create the new contact, redirect to GET /contacts

包含類似於以下的 HTML

<div>
    <form action='/contacts' method="post">
      <!-- form for adding contacts -->
    </form>
    <table>
      <!-- contacts table -->
    </table>
</div>

到目前為止,這是標準的 Web 1.0 應用程式,到目前為止,資料 API 和超媒體 API 的需求還沒有太大分歧,儘管值得注意的是,超媒體 API 是自我描述的,並且可以修改(例如,更改建立聯絡人的 URL)而不會破壞超媒體應用程式。

現在我們到了需要 htmx 的部分:偶爾輪詢伺服器以獲取表格的更新。為此,我們將添加一個新的端點 /contacts/table,它只呈現聯絡人表格

  GET /contacts -> render the form & contacts table
  POST /contacts -> create the new contact, redirect to GET /contacts
  GET /contacts/table -> render the contacts table

然後向表格添加輪詢觸發器

<div>
    <form action='/contacts' method="post">
      <!-- form for adding contacts -->
    </form>
    <table hx-trigger="every 30s" hx-get="/contacts/table" hx-swap="outerHTML">
      <!-- contacts table -->
    </table>
</div>

在這裡我們看到了超媒體 API 和資料 API 開始分歧。這個新的端點完全由超媒體需求驅動,而不是資料模型需求。如果應用程式的超媒體需求發生變化,此端點可能會消失;其形式可能會發生巨大變化等等,這是完全可以接受的,因為系統是自我描述的。

既然我們已經更新了 HTML 以使用 htmx 進行輪詢,我們不妨讓表單也使用 htmx,以獲得更好的 UX 體驗

<div>
    <form action='/contacts' method="post" hx-boost="true">
      <!-- form for adding contacts -->
    </form>
    <table hx-trigger="every 30s" hx-get="/contacts/table" hx-swap="outerHTML">
      <!-- contacts table -->
    </table>
</div>

如果我們選擇,我們可以為輸入的伺服器端驗證、動態表單等添加額外的端點。這些端點將由超媒體需求驅動,而不是任何形式的資料模型考量:我們考慮的是我們試圖透過應用程式實現什麼。

#API 變動

這篇短文的關鍵點是:API 變動在超媒體系統中是可以接受的,因為超媒體系統中的訊息是自我描述的。我們可以隨意改動 API,而應用程式不會崩潰:人類用戶只會看到新的超媒體 (HTML),並選擇他們想要執行的操作。

與電腦相比,人類擅長決定做什麼,並且可以合理地接受變更。

這與資料 API 形成對比。資料 API 如果不修改,則無法修改客戶端程式碼,因此在變更時必須更加嚴格。資料 API 也面臨提供更高層次表現力的壓力,以便它們可以在不修改的情況下滿足更多的客戶端需求。

#結論

在設計超媒體 API 時,您應該使用與資料 API 不同的設計思維模式。變動不是那麼令人擔憂,提供良好的超媒體體驗所需的端點應該是您的主要目標。

</>