资源状态管理 — HATEOAS:把「下一步能做什么」写进响应
资源状态管理 — HATEOAS
这一章讲什么: 到第 04 章为止,客户端其实还欠着一样东西——每个端点的地址。 它得查文档、把
/orders/{id}/cancel这类路径硬编码进自己的程序;服务器哪天改个路径,所有客户端跟着崩。 HATEOAS 把这件事倒过来:响应自己带路。订单还是「待处理」,响应里就附「取消」「确认」的链接;已发货,就只剩「查物流」。 客户端不认识任何 URL,只跟着链接走。这是 Roy Fielding 博士论文里定下的 REST 核心机制,也是现实 API 里最少被真正做到的一条——这一章讲它是什么、为什么值得、以及怎么落地。
1. 顶层全景:状态转移图,和一张会自己带地图的订单
先解释这个拗口的名字。HATEOAS 是 Hypermedia as the Engine of Application State 的首字母缩写,直译「超媒体作为应用状态的引擎」。拆开读:应用状态(客户端走到哪一步了)不是靠客户端脑子里记的流程图推进的,而是靠响应里的超媒体(链接)推着走的——链接就是引擎1。
书里给的类比是带导游的博物馆:你只管从大门进去(初始 URI),走到每个展厅,导游(服务器)根据你现在的位置带你去下一个展厅;路线是导游实时算的,你不需要预设地图2。再现代化一点:像导航软件,根据当前路况实时重算路线。
本章的主线例子,贯穿到底——一张订单的状态机:
订单 67890 的一生(状态转移图):
pending ──confirm──→ confirmed ──ship──→ shipped ──track──→ (在途)
│ │
└────cancel────┐ └────cancel────→ cancelled
▼
cancelled
图说:每个箭头是一次合法的状态转移。HATEOAS 的要求:响应里只放「从当前状态出发
的出边」对应的链接。pending 的订单给 cancel/confirm/update;cancelled 的订单,
这些链接全部消失——客户端程序里不需要写「if 已取消就不显示取消按钮」这种判断。每一步的具体响应长什么样、链接怎么设计、出错时怎么办、链接按什么条件出现——这一章全部围绕这张订单图展开。
2. Fielding 的原始要求:除入口外,不许有先验知识
书里引用 Fielding 的表述,这是全章的理论地基,值得原样理解:进入 REST API 时,除了一个初始 URI(像一个书签),客户端不应当带任何先验知识;从那一刻起,任何应用状态的转移,都必须由「客户端从收到的表述中选择服务器提供的选项」来驱动3。
这句话的锋芒在「任何」两个字上。它意味着:
- 客户端代码里不允许出现
/orders/{id}/cancel这种拼路径的逻辑; - 流程不由客户端的流程图决定——服务器说有哪些选项,客户端才能看到哪些选项;
- 服务器端改了路径、加了步骤、调了流程,客户端无感——因为它从来不知道路径。
书里把这叫解耦(decoupling):超媒体把客户端从端点列表里解放出来,系统内部结构被抽象在链接背后。这是它的设计理由,不是什么洁癖——它直接回答了「API 总在变,客户端凭什么不坏」这个第 02 章版本策略只答了一半的问题4。
语义与元数据:链接不是裸 URL
一个裸的 /orders/67890?status=cancel 告诉客户端「有个地址」;但客户端还需要知道这是什么动作、怎么去触发。所以超媒体控件(hypermedia control,就是响应里那段带链接的结构)要自描述,书里用三样东西补足语义5:
| 件 | 作用 | 主线例子里的值 |
|---|---|---|
rel(relation,关系) | 这个链接和当前资源是什么关系 | cancel、confirm、update、self |
method | 用什么 HTTP 方法去触发 | POST、PUT、GET |
href | 去哪里触发 | /orders/67890?status=cancel |
再看元数据(metadata):它回答「这个资源处于生命周期的哪一步、这份数据什么时候失效」——响应里的 version: "1.2"、expiresAt: "2035-03-04T10:00:00Z" 这类字段。语义定义「能对资源做什么」,元数据定义「资源此刻的处境」,两者合起来,客户端不需要任何先验知识就能做出正确动作6。
主线例子的完整形态(原书订单例的第一版):
{
"orderId": 123, "status": "pending", "totalAmount": 99.99,
"_links": {
"self": { "href": "/order/123" },
"ship": { "href": "/order/123?status=ship", "method": "POST" },
"cancel": { "href": "/order/123?status=cancel", "method": "POST" }
},
"metadata": { "version": "1.2", "expiresAt": "2035-03-04T10:00:00Z" }
}status: "pending" 告诉客户端处境;三个链接只覆盖当前状态下合法的动作。订单一旦被取消,ship 和 cancel 从响应里消失——状态机的规则由服务器执行,而不是靠客户端自觉7。
超媒体控件的三条品性
书里总结:设计良好的超媒体控件是解耦的(客户端靠响应里的指令发现新状态,不绑死端点)、自描述的(每个链接都带元数据说明用途、动作、与资源的关系,客户端不需要外部知识就能决定动不动它)、情境化的(可选动作随资源状态和客户端在流程中的位置实时变化)8。
3. 设计超媒体控件:一致性、聚簇与标准格式
一致性:让客户端敢闭着眼睛跟链接
链接的设计要和 API 的其余部分一样守规矩:关系名统一(不同资源上的「更新」都叫 update)、HTTP 方法可预期(self 总是 GET)、链接对象的结构固定(总是 href + method + rel 三字段)。书里强调:一致性让客户端能安全地读懂并跟随任何响应里的链接,不用怕下一步有歧义;同一种资源复用同一套链接结构,设计也有了复用性,开发者可以把精力放在业务逻辑上,而不是每次重新发明导航小零件9。
书里给的图书例子,把「链接随状态出现」演示得很干净:一本书的响应里,purchase 链接只在有货时出现(availability: "In Stock")——动作被放在了应用状态的整体语境里10。
聚簇:链接在响应里怎么摆
链接的摆放位置本身就是设计:把同类的链接聚在一起(所有更新相关的放一个簇)、给链接加标题或描述性属性,响应的可读性就上去了——这些线索本来是给程序看的,但人读文档时也受益。书里称之为自我文档化:组织良好的链接让 API 自己成为文档,比外部文档更直觉11。
回到主线例子,订单 67890 处于 pending 时的完整链接集,每个链接都自描述:
{ "orderId": 67890, "customer": "John Doe", "status": "pending",
"items": [ { "product": "Widget A", "quantity": 2, "price": 9.99 },
{ "product": "Widget B", "quantity": 1, "price": 19.99 } ],
"links": {
"self": { "href": "/orders/67890", "method": "GET", "rel": "self" },
"cancel": { "href": "/orders/67890?status=cancel", "method": "POST", "rel": "cancel" },
"update": { "href": "/orders/67890", "method": "PUT", "rel": "update" },
"confirm": { "href": "/orders/67890?status=confirm", "method": "POST", "rel": "confirm" } } }客户端此刻能做的四件事,不用查任何文档:取订单(self)、取消(cancel)、改(update)、确认(confirm)12。
标准格式:HAL、JSON:API、Siren
自己发明链接字段名(_links?links?href?)不如直接采用现成的标准格式。书里点了三个已成事实标准的名字:HAL(Hypertext Application Language,用 _links 放链接、_embedded 放内联的相关资源)、JSON:API、Siren。采用标准的收益很实际:现成的客户端库与工具、跨团队的一致性、以及「第三方工具能假设一种固定格式」这件在自定义方案里永远做不到的事13。
HAL 在主线例子上加一笔,演示 _embedded 的价值:
{
"_links": {
"self": { "href": "/orders/67890" },
"cancel": { "href": "/orders/67890?status=cancel", "method": "POST" },
"update": { "href": "/orders/67890", "method": "PUT" }
},
"_embedded": {
"customer": { "customerId": "12345", "name": "John Doe",
"_links": { "self": { "href": "/customers/12345" } } }
}
}_embedded 把下单客户内联进订单响应——客户端要显示客户名,不用再发一次请求;想拿客户的完整档案,顺着内联里的 self 链接走。相对路径(href 不带域名)让整套结构可以挂在任何基础 URL 下运行14。
链接的取舍:策展,而不是堆砌
加哪些链接、不加哪些,是书里单列的一节(iterative link curation,迭代式链接策展):每个链接都要有明确目的;链接太多会让响应臃肿、客户端迷惑,太少又会在状态转移图上留窟窿。取舍标准:优先支撑最频繁、最关键的状态转移。服务器还可以按用户权限、资源状态定制链接——同一张订单,客服看到的链接和普通用户看到的可以不同;多路径(cancel 与 modify 并列)还降低了「流程太 rigid 导致客户端走错」的错误率。链接结构要根据真实使用情况的反馈持续调整15。
4. 错误也是状态:出错时谁来指路
HATEOAS 最容易被忽略的推论:状态转移图里必须包含失败路径。书里立的原则:超媒体系统必须管理失败,不只是成功——如果更新失败(冲突、坏请求),响应要引导客户端走向修复,而不是扔一个错误码完事。做法是把恢复路径直接烤进响应:文档链接、日志入口、重试端点16。
主线例子的失败分支:
{
"error": "Conflict", "message": "The resource is locked",
"_links": {
"retry": { "href": "/resource/123?status=retry", "method": "POST", "rel": "retry" },
"help": { "href": "/help/resource-lock", "method": "GET", "rel": "help" }
}
}冲突发生后,客户端拿到的不是终点,是两条路:重试,或者去读这份错误该怎么处理的文档。书里称这为「自愈式」体验:故障恢复选项显式化,客户端更韧,停机时间更短17。
5. 条件链接:时间、地点和权限来决定链接的出现
书里最高级的一招:链接可以按外部条件动态出现。例子是一场 2035 年 5 月 15 日在纽约的户外音乐会,三个链接各带一个 condition 表达式18:
| 链接 | 出现条件 | 对谁可见 |
|---|---|---|
buyTickets(购票) | 日期在 5 月 1–14 日 且 用户在美国 | 演出前一周内的美国用户 |
viewReplay(看回放) | 演出已过去 或 用户在美国之外 | 错过直播的人 |
joinLiveStream(看直播) | 演出当天 且 用户不在美国 | 海外观众 |
图说:同一张演唱会资源,三个用户在同一时刻看到的链接集完全不同——
服务器按「时间 + 地理位置」算出每个人合法的下一步。这就是「context aware」。条件链接的收益书里点了两条:响应里没有噪音链接(你不会看到「购票」按钮出现在演出结束后),客户端被引导到最相关的动作。代价(我们补):condition 表达式本身成了服务器与客户端之间的新契约——表达式语言、可用的处境变量(user.geo 从哪来),都得写进文档,否则自描述性就破了洞。
6. 安全:链接泄露的正是「你能做什么」
这一节把第 06 章的引子提前埋好:链接清单本身就是敏感信息——它声明了这个用户能做什么。所以书里立了三条规矩:链接按认证与授权动态生成(没权限的用户根本不该看到敏感链接);所有会改变状态的链接都要防常见的 Web 攻击,比如 CSRF(Cross-site Request Forgery,跨站请求伪造:诱导已登录用户的浏览器去发一个它有权发的请求);安全测试与审计要持续做,不是一次性的19。
7. 性能、文档、测试与运维:落地时的七件杂事
书的后半章是落地清单,逐条过:
- 性能:链接会撑大响应。对策是有选择地放链接 + 载荷压缩(第 07 章的 Gzip);并且要用一项项量出来的指标(比如响应耗时)监控超媒体对响应速度的实际影响,在「导航线索充分」和「响应轻」之间找平衡20。
- 缓存:HATEOAS 与缓存有张力——响应内容随状态变,缓存的副本可能 stale(过期)。对策是缓存失效(cache invalidation,内容变了让旧缓存作废)与条件请求(第 03 章的 ETag)组合拳:缓存「经常访问且状态稳定」的响应,对动态部分保持实时21。
- 文档:自描述不等于不用文档——文档要解释每个 rel 的含义、客户端该怎么遍历链接;它是排查「行为不一致」时的总依据。书里说的是「两手都要硬」:自描述消息 + 清晰外部文档,新手和老手都照顾到22。
- 测试:集成测试要自动验证「每个链接都能工作、每条状态转移都走得通」,覆盖错误状态和边角情况;书里称这种测试是 HATEOAS 系统上线的门禁23。
- 日志分析:客户端怎么发现和使用资源,日志里看得一清二楚——哪条流程卡住了、哪个链接从没人点,都是改链接结构的依据24。
- 回退机制(fallback):主链接因临时故障不可用时,响应给出一条冗余路径,把客户端引向中间状态;分布式系统里网络抖动是常态,回退让 API「永不把客户端晾在半路上」25。
- 语义化版本(semantic versioning):链接里写上 MAJOR.MINOR.PATCH 三段式版本号——MAJOR 变=有破坏性改动,MINOR 变=加了新功能,PATCH 变=修了 bug。客户端按自己的能力选路径,迁移风险骤降;这是超媒体 API 长期可维护的骨架26。
- 模块化:把超媒体响应拆成数据、链接、元数据、错误四个模块,各改各的——加一个新链接不强迫其他模块动,这就是「响应内部的解耦」27。
8. 作者的判断与证据
- Fielding 的原始要求是引文级的,本章最有分量的「证据」就是那段「除初始 URI 外无先验知识」的引述——这是 REST 理论自己给自己的定义,不是作者的发明28。
- HAL/JSON:API/Siren 是事实标准,这是行业状态,有规格文档背书。
- 作者的判断(值得标出):「HATEOAS 是当代 REST 的核心设计伦理——每个状态都从转移中来」。这个「每个状态都来自一次转移」的表述,把 HATEOAS 从「可选功能」升格为「REST 之所以是 REST 的判据」——这是作者的立场,不是业界共识:现实中绝大多数自称 REST 的 API 都不做 HATEOAS,行业里把这叫「REST 但不做超媒体」的普遍妥协。书里没提这个妥协,这是它的明显留白(见下节)。
- 诚实的部分:性能、安全、文档、测试这四节的语气是「这是杂事清单,每件都得有人管」,没有夸大 HATEOAS 的便宜。
9. 边界与局限
- 最大留白:现实中的「REST 不带 HATEOAS」。书里把 HATEOAS 讲成核心,却没讨论为什么业界很少做:客户端开发体验(跟着链接写流程比硬编码 URL 绕)、缓存友好性(个性化响应难缓存)、以及机器消费时代(程序对程序的集成往往有 OpenAPI 契约,不靠运行时链接)。这些反方论据不在书中。
condition表达式是自造约定。 书里条件链接的表达式写法是示例性的,没有对应任何标准;直接抄会造出一个私有契约。- 「取消=POST 到 ?status=cancel」这类把动作编码进查询参数的做法,严格说模糊了资源和动作:更纯粹的写法是
cancel作为订单的子资源POST /orders/67890/cancel,或第 03 章的PATCH {status:"cancelled"}。书里为了演示链接机制用了查询参数风格——教学上清楚,工程上见仁见智。 - 性能一节的深度有限:「选择性放链接」具体怎么选(按角色?按使用频率?按响应大小预算?),书里没给方法。
- 错误恢复链接的「help」指向
/help/resource-lock这类相对路径,在真实多服务系统里,文档服务的地址恰恰是该被 HATEOAS 管理的对象之一——「链接该指向哪」的答案本身就是链接,这种「答案本身又是自己」的循环问题书里没碰。
10. 可带走的
本章主线例子一行走完: 订单 67890 的一生——pending 时响应带 self/cancel/update/confirm 四个链接;confirm 之后 cancel 消失;出错时响应带 retry/help 两条恢复路;演唱会资源按「时间+地区」给不同的人发不同的链接。状态机的规则由服务器用链接执行,客户端只负责跟着走。
- HATEOAS 的定义一句话:应用状态的引擎是响应里的链接,不是客户端脑子里的流程图。
- Fielding 的原话记牢:除初始 URI 外,客户端不许带先验知识——这是判据,不是建议。
- 超媒体控件三件套:
href+method+rel;三样缺一,客户端就得查文档,自描述性就破了。 - 链接随状态出现: cancelled 的订单不该显示取消按钮——让服务器执行状态机规则,别让客户端写 if。
- 错误也是状态:失败响应里给恢复链接(retry/help),客户端才有韧性。
- 条件链接消灭噪音:按时间、地点、权限算「这个人的合法下一步」,响应里没有多余选项。
- 用标准格式(HAL/JSON:API/Siren),别发明私有的链接写法——私有写法的维护成本迟早追上你。
- 链接本身是敏感面:链接清单泄露用户能做什么;动态生成 + 防 CSRF + 持续审计。
- 超媒体与缓存有张力:个性化响应难缓存,用选择性链接 + 缓存失效 + ETag 组合拳收口。
- 语义化版本是迁移的骨架:MAJOR.MINOR.PATCH 写进链接,客户端按能力选路。
11. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| HATEOAS 的定位与 GPS 类比 | Resource State Management | text/12-fm-introduction.txt:64(搜「GPS」) · :64(搜「interactive guides」) |
| Fielding 原始要求 | Resource State Management | text/12-fm-introduction.txt:70(搜「no prior knowledge beyond an initial URI」) |
| 解耦与设计理由 | Resource State Management | text/12-fm-introduction.txt:73(搜「coupling problem」) |
| 语义与元数据 | Resource State Management | text/12-fm-introduction.txt:79(搜「Semantics define the operations」) |
| 订单例第一版(_links + metadata) | Resource State Management | text/12-fm-introduction.txt:94(搜「totalAmount」) · :142(搜「expiresAt」) |
| 超媒体控件三品性 | Resource State Management | text/12-fm-introduction.txt:157(搜「decoupled, self-describing, and contextual」) |
| 一致性与图书例子 | Resource State Management | text/12-fm-introduction.txt:163(搜「consistency」) · :169(搜「The Great Gatsby」) |
| 订单 67890 四链接 | Resource State Management | text/12-fm-introduction.txt:259(搜「orderId」) · :373(搜「may」) |
| 状态转移图 | Resource State Management | text/12-fm-introduction.txt:390(搜「state transition graph」) |
| HAL 与 _embedded | Resource State Management | text/12-fm-introduction.txt:409(搜「Hypertext Application Language」) · :415(搜「_links」) · :454(搜「_embedded」) |
| 链接策展 | Resource State Management | text/12-fm-introduction.txt:496(搜「curation」) · :499(搜「multiplicity」) |
| 标准格式与工具生态 | Resource State Management | text/12-fm-introduction.txt:511(搜「HAL, JSON:API, and Siren」) |
| 错误处理与恢复链接 | Resource State Management | text/12-fm-introduction.txt:514(搜「manage failure」) · :520(搜「Conflict」) |
| 性能优化 | Resource State Management | text/12-fm-introduction.txt:571(搜「bloat」) |
| 安全:动态生成与 CSRF | Resource State Management | text/12-fm-introduction.txt:574(搜「authentication and authorization」) |
| 文档互补 | Resource State Management | text/12-fm-introduction.txt:577(搜「self-descriptive messages」) |
| 条件链接(演唱会例) | Resource State Management | text/12-fm-introduction.txt:586(搜「conditional links」) · :592(搜「Outdoor Concert」) |
| 日志分析与测试门禁 | Resource State Management | text/12-fm-introduction.txt:681(搜「Log analysis」) · :684(搜「gates」) |
| 回退机制 | Resource State Management | text/12-fm-introduction.txt:690(搜「fallback mechanism」) |
| 语义化版本 | Resource State Management | text/12-fm-introduction.txt:693(搜「MAJOR.MINOR.PATCH」) |
| 模块化响应与缓存 | Resource State Management | text/12-fm-introduction.txt:699(搜「modularize」) · :702(搜「cache invalidation」) |
| 结论:每个状态来自转移 | Resource State Management | text/12-fm-introduction.txt:499(搜「each state comes out of a transition」) |
Footnotes
-
出处:「CHAPTER 5 Resource State Management」第 35 段(
text/12-fm-introduction.txt:35,搜「HATEOAS」)。原文对全名的展开与机制定位:「embeds navigational cues directly into API responses... informs clients of the next state transitions, based on the current resource state」。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 70 段(
text/12-fm-introduction.txt:70,搜「guided museum tour」)。原文:「HATEOAS is like a guided museum tour... The guide adapts the tour in real time, suggesting new paths... without needing a preset map or prior knowledge of the museum's layout.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 70 段(
text/12-fm-introduction.txt:70,搜「no prior knowledge beyond an initial URI」)。原文:「a REST API should be entered with no prior knowledge beyond an initial URI... any application state transition must be driven solely by client selection of server-provided choices present in the received representations」。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 73 段(
text/12-fm-introduction.txt:73,搜「client-server coupling problem」)。原文:「HATEOAS solves a client-server coupling problem... Clients make decisions about what steps to take through the hypermedia links embedded in API responses.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 79 段(
text/12-fm-introduction.txt:79,搜「Semantics define the operations」)。原文:「Semantics define the operations a client can perform by making resource state transitions. Metadata, on the other hand, adds additional context to resources」。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 82 段(
text/12-fm-introduction.txt:82,搜「frees clients from any preconceived knowledge」)。原文:「Together, semantics and metadata provide the framework that frees clients from any preconceived knowledge of API structure.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 88–151 段(
text/12-fm-introduction.txt:88,搜「orderId」;:91,搜「status": "pending"」;:151,搜「The resource's state determines which actions are available」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 157 段(
text/12-fm-introduction.txt:157,搜「decoupled, self-describing, and contextual」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 163 段(
text/12-fm-introduction.txt:163,搜「consistency of hypermedia control design」)。原文:「If the links are designed consistently, clients can parse and follow them safely without risk of ambiguity in any subsequent step.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 169–250 段(
text/12-fm-introduction.txt:169,搜「The Great Gatsby」;:250,搜「a purchase link exists only because the book is available」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 406 段(
text/12-fm-introduction.txt:406,搜「self-documenting interface」)。原文:「Through an organization of links, the API itself becomes a self-documenting interface, more intuitive than external documentation.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 259–388 段(
text/12-fm-introduction.txt:259,搜「orderId」;:373,搜「The client may」)。四个动作与对应方法的清单见原文。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 511 段(
text/12-fm-introduction.txt:511,搜「HAL, JSON:API, and Siren」)。原文:「These specifications cover the nuances of hypermedia design... They enable the integration of third-party libraries and tools assuming a standard format in hypermedia responses.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 415–490 段(
text/12-fm-introduction.txt:415,搜「_links」;:454,搜「_embedded」;:490,搜「relative paths」)。原文:「These links are relative paths, so they are adaptable based on the base URL of the API.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 496 段(
text/12-fm-introduction.txt:496,搜「curation」)与第 499 段(text/12-fm-introduction.txt:499,搜「user privileges」)。原文:「preferring those links that support the most frequent or critical state transitions」;服务器可按权限、资源状态定制链接。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 514 段(
text/12-fm-introduction.txt:514,搜「manage failure」)。原文:「A hypermedia system must manage failure, not just success... Bake these recovery paths directly into your API responses.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 520–565 段(
text/12-fm-introduction.txt:520,搜「Conflict」;:565,搜「fault tolerance」)。原文:「links can give the client its next steps... makes the overall client experience more robust in case of failure」。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 586–677 段(
text/12-fm-introduction.txt:586,搜「conditional links」;:592,搜「Outdoor Concert」)。三个链接的条件原文逐条列出:buyTickets 要求日期在 2035-05-01 至 05-14 且用户 geo 为 US;viewReplay 要求演出已过或用户不在 US;joinLiveStream 要求当天且用户不在 US。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 574 段(
text/12-fm-introduction.txt:574,搜「Cross-site Request Forgery」)。原文:「Links declare what a user can do. So generate them dynamically, based on authentication and authorization.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 571 段(
text/12-fm-introduction.txt:571,搜「Selective link inclusion and payload compression」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 702 段(
text/12-fm-introduction.txt:702,搜「cache invalidation and conditional requests」)。原文:「caching also needs to be adequately controlled, to ensure some dynamic state transitions are correct and up to date」。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 577 段(
text/12-fm-introduction.txt:577,搜「pair self-descriptive messages with clear external docs」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 684 段(
text/12-fm-introduction.txt:684,搜「This level of quality assurance typically gates」)。原文:「A rigorous testing regimen is not just a best practice but a necessity... typically gates a system with HATEOAS to be released into a production environment.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 681 段(
text/12-fm-introduction.txt:681,搜「most common sequences of requests」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 690 段(
text/12-fm-introduction.txt:690,搜「fallback mechanism」)。原文:「A fallback mechanism never leaves clients high and dry... alternative routes may be rerouted programmatically around failure points.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 693 段(
text/12-fm-introduction.txt:693,搜「MAJOR.MINOR.PATCH」)。原文:「MAJOR for breaking changes. MINOR for new features. PATCH for bug fixes.」 ↩ -
出处:「CHAPTER 5 Resource State Management」第 699 段(
text/12-fm-introduction.txt:699,搜「Split them into parts: data, links, metadata, errors」)。 ↩ -
出处:「CHAPTER 5 Resource State Management」第 70 段(
text/12-fm-introduction.txt:70,搜「Roy Fielding explains」)。书里明确说这是 Fielding 的表述(出自其博士论文),不是我们作者的发明。 ↩