2

编辑:为了澄清,这个问题涉及在 HATEOAS APIs 上构建 GUI 应用程序,如何设计基于超媒体“可发现性”(即动态)原则的界面,特别是处理避免“链接”回“home”的纯“模态”GUI " 表示应该“始终开启”的全局功能(由超媒体入口 API 点表示)。


在严格的 REST API 实现中,利用超媒体作为应用程序状态引擎 (HATEOAS),使用哪些模式(如果有)来指示/表示全局“始终有效”的操作(如果这样的概念甚至真的存在于 REST 中)?

元问题是,你能完全“排除”重复的超媒体吗?

通过简化示例,假设我们有一个/version资源Allow: OPTIONS HEAD GET。该资源不依赖任何东西,并且永远不会受到其他地方可能发生的任何状态转换的影响。

  1. 是否要求/version超媒体与每个其他资源请求一起简单地发送?

  2. 或者另一种模式,客户端行为链接回Home(可能缓存)然后触发我们始终有效的/version调用?(GUI 术语中的“模态”模式 - 关闭此资源,返回首页,然后继续)

  3. 或者是否有某种方法/模式可以为任何给定的应用程序创建独立的解耦模块?(也许是某种命名空间?)

在一个复杂但松耦合的 API 中,选项 1最终被埋在超媒体地狱中,每次资源调用都会重复 80-95% 的有效负载。这似乎“正确”但太讨厌了。选项 2 会导致 GUI 客户端行为出现奇怪的怪癖(隐藏有效元素,直到您“回家” - 模态类型操作)或 GUI 客户端硬编码它“知道”的带外操作的许多不平静的假设总是有效的。

选项 3 与我最初的问题有关:是否有一个标志或其他模式来指示可以发送一次(例如使用根/主资源)然后从后续响应中“排除”的全局有效操作?

4

2 回答 2

2

嗯,这里发生了几件事。

首先,您可以简单地添加指向任何常见“全局”资源的链接。尽管我很讨厌将 REST 架构与网站进行比较,但网站是一个合适的示例。考虑一下 SO 上的许多资源都具有指向通用“全局”资源的链接——例如主页、/questions、/tags、/badges 和 /users。

资源是“静态的”并且从不更改这一事实不会影响您是否通过另一个资源作为 HATEOS 的一部分将资源作为链接提供,这是一个正交问题。

第二点是,没有什么可以说整个服务可以从每个资源中持续访问。您可以在您的服务中拥有“众所周知的”入口点,并且这些入口点可以有据可查(外部)。唯一的缺点是,如果某个关系的 URL 发生变化(例如 /questions 到 /questions-2),那么客户端可能不会自动获取这些 URL。但这可能不是问题,因为通过更改 URL,您可能会更改影响客户端的其他内容(例如有效负载),以至于旧客户端可能与新 URL 不兼容。

让客户“知道”事物在嵌套系统中的位置也不是问题。例如,如果他们“知道”,如文档所述,他们只能从 /home 资源访问 /version,并且每个其他资源都有到 /home 的路径(直接或间接),那么这不是问题任何一个。当它想要 /version 时,它应该知道获取它的路径是什么。

只要客户根据您告诉它的内容而不是“它的想法”来遍历图表,那么一切都很好。如果客户端当前正在处理 /blog/daily_news/123 资源,并且它有一个指向“parent”的链接 rel,其 url 是 /blog,并且 /blog 有一个指向 /version 的链接 rel “version”,那么客户端可以遍历图(遍历父 rel 到 /blog,版本 rel 到 /version)。客户端不应该做的(除非另有说明)是它不应该假设它可以随时访问 /version 。由于它没有从 /blog/daily_news/123 链接,客户端不应该只是跳到它。rel 不存在,所以客户“不知道”。

这是关键点。它不存在的事实意味着它现在不是一个选项,无论出于何种原因,也不是客户端任务强制指出这一点,因为 URL 空间不在它的手中,它在服务的手中。服务控制它,而不是客户端。

如果 /version 突然消失,那是另一个问题。也许他们超时并且不再被允许“看到” /version,也许你删除了它。此时客户端将简单地出错“找不到版本 rel”,然后退出。这是一个无关的问题,只是一个事实(当资源突然消失在你的背后,你还能做什么)。

问题补充:

如果我理解这意味着:如果 /home 没有过期,并且我们导航到 /blog(其中包含返回 /home 的 rel),那么 /home 的 rel 方法仍然可以立即从 /blog 中“访问”,对吗?

不,不是。这是关键点。除了一些专门记录的全局资源(带外),您不应遍历当前资源中未指定的任何链接。/home 是否未过期根本不相关。

服务器当然可以发送适当的缓存指令,让您知道您可以缓存 /home 一段时间,但您仍然应该遍历 rel 到 /home 以获取您认为存在的任何链接。

如果 /home 很好地缓存在您的客户端上,那么这种遍历实际上是免费的,但从逻辑和语义上讲,您应该坚持遍历链接的协议。

因为如果它没有被缓存,那么你根本不知道当你回来时会有什么 rels 存在。是的,99.999999% 的时间它总是相同的,并且为服务器没有发送适当的缓存头而感到羞耻,但根据定义,服务器并没有向你承诺任何东西,所以你,客户端和它,服务器,一次又一次地吃掉一个有效的静态资源的处理成本。

通过强制您的客户遵循这些步骤,也许通过缓存和预处理进行内部优化以使这些静态遍历快速有效,您坚持使用 HATEOS 模型,并遵循系统以使其最佳而不是预先假设在代码级别并跳过您认为已经拥有的 rels。

这样,无论服务器做什么,您的代码都将始终有效。谁知道他们什么时候可以打开或关闭缓存,你的代码当然不应该关心,而不是在决定是否取消引用链接的级别。

HATEOS 的前提是服务器负责并授权其 URL 空间。在没有服务器指导的情况下随意跳动是不合规范的,这不是您要导航的图表。REST 用于更粗粒度的操作,但适当的缓存等可以使您的客户端快速高效地跳过这些环节。

于 2013-07-24T04:07:28.373 回答
1

也许我误解了这个问题,但似乎客户端缓存应该解决这个问题。查找 Expires 和 Cache Control 标头。

于 2013-07-24T01:47:14.977 回答