一个 超媒体 API 是一个返回 hypermedia 的 API,通常是通过 HTTP 返回 HTML。这种风格的 API 与不返回超媒体的数据 API 有所区别。今天最常见的后一种风格的 API 是无处不在的 JSON API。
这两种不同类型的 API 具有截然不同的设计需求,因此在创建时应该使用不同的设计约束并采用不同的目标。
超媒体 API:
另一方面,数据 API:
如今,API 通常被视为 JSON-over-HTTP 的形式。这些几乎总是面向数据的 API 而非超媒体 API,尽管偶尔会将超媒体概念融入其中(通常对最终用户益处不大)。行业已经开始 远离 REST-ful API,因为它开始 认识到将数据 API 拟合到 REST-ful 模型中的问题。
这是一个好现象:行业应该质疑数据 API 世界中的 REST-ful 理念,并开始审视那些更好地服务于特定网络架构的旧客户端-服务器技术,而将 REST 留给它被创造时所描述的网络架构:超媒体 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 而不会破坏应用:人类用户只需看到新的超媒体(HTML)并选择他们想要执行的操作。
与计算机相比,人类 擅长决定该做什么 并且对变化相当适应。
这与数据 API 形成对比。数据 API 不能在不破坏客户端代码的情况下进行修改,因此必须在变化上更加 自律。数据 API 还面临提供更高表达性水平的压力,以便在不修改的情况下满足更多客户端需求。
在设计超媒体 API 时,您应该使用不同于数据 API 的设计心态。变动 不再是主要问题,提供您需要的好超媒体体验的端点应该是您的首要目标。