RESTful API 运行时可发现性/HATEOAS 客户端设计

对于我参与的一家 SaaS 初创公司,我正在构建一个 RESTful web API 和几个使用它的不同平台上的客户端应用程序。我想我已经搞定了 API 但现在我要去找客户了。正如我一直在阅读关于 REST 的文章,我发现 REST 的一个关键部分是 发现,但是对于发现真正意味着什么,在两种不同的解释之间似乎有很多争论:

  1. 开发人员发现 : 开发人员将大量的 API 细节硬编码到客户端,比如资源 URI、查询参数、支持的 HTTP 方法,以及他们通过浏览文档和实验 API 响应发现的其他细节。这种类型的发现 IMHO 需要冷静的链接和 API 版本问题,并导致客户机代码与 API 之间的硬耦合。这并不比使用一个良好文档化的 RPC 集合好多少。

  2. 运行时发现 -客户端应用程序本身能够在很少或没有带外信息的情况下找出它需要的所有内容(大概只需要了解 API 处理的媒体类型)链接可以是热点。但是,为了使 API 非常有效,似乎需要为查询参数建立大量链接模板,这使得带外信息又回来了。可能还有其他我没有想到的困难,因为我还没有到达开发的那个点。但我确实喜欢松耦合这个主意。

运行时发现似乎是 REST 的圣杯,但是我看到关于如何实现这样一个客户机的讨论非常少。我发现的几乎所有 REST 源代码似乎都假定是开发人员发现的。有人知道一些运行时发现资源吗?最佳实践?例子还是实际代码的库?我使用 PHP (Zend Framework)为一个客户机工作。Objective-C (iOS)用于另一个。

考虑到开发者社区目前的工具和知识,运行时发现是一个现实的目标吗?我可以编写我的客户端以一种不透明的方式处理所有 URI,但是如何最有效地这样做是一个问题,特别是在低带宽连接上。无论如何,URI 只是等式的一部分。运行时上下文中的链接模板如何?除了发出大量的 OPTION 请求之外,如何交流支持哪些方法?

17824 次浏览

你做了你的家庭作业,你得到了它的核心: 运行时发现是圣杯。别追了。

UDDI 讲述了一个关于运行时发现的辛酸故事: http://en.wikipedia.org/wiki/Universal_Description_Discovery_and_Integration

这绝对是个棘手的问题。在 Google,我们已经实现了我们的 Discovery Service,我们所有的新 API 都是基于该服务构建的。DR 版本是我们生成一个类似于 JSON Schema 的规范,我们的客户机可以动态地解析其中的许多规范。

这意味着开发人员更容易升级 SDK,我们也更容易/更好地进行维护。

这绝不是完美的解决方案,但我们的许多开发人员似乎喜欢。

请参阅 链接了解更多细节(并确保观看视频)

真有意思。你所描述的基本上是 HATEOAS 原则。你问的仇恨是什么?看看这个: http://en.wikipedia.org/wiki/HATEOAS

在外行的术语,HATEOAS 意味着链接下面。这种方法将客户端与特定 URL 分离,并使您可以灵活地更改 API,而不会破坏任何人。

我认为 HATEOAS 的重点不在于它是什么神圣的客户端,而在于它将客户端与 URI 更改隔离开来——它假设您使用的是已知(或开发人员发现的自定义)链接关系,这将允许系统知道对象的哪个链接是可编辑表单。重要的一点是使用能够感知超媒体的媒体类型(例如 HTML、 XHTML 等)。

你写道:

为了使 API 非常有效,似乎需要为查询参数建立大量链接模板,这使得带外信息又回来了。

如果该链接模板在以前的请求中提供,则不存在带外信息。例如,一个 HTML 搜索表单使用链接模板(/search?q=%@)来生成一个 URL (/search?q=hateoas) ,但是客户端(网络浏览器)除了知道如何使用 HTML 表单和 GET之外什么都不知道。

在调用一个 API‘ RESTful’之前,需要满足的一个要求是,应该可以在该 API 之上编写一个通用客户机应用程序。使用通用客户机,用户应该能够访问所有 API 的功能。泛型客户端是一个客户端应用程序,它不假定任何资源具有超出媒体类型定义的结构的特定结构。例如,Web 浏览器是一个通用的客户端,它知道如何解释 HTML,包括 HTML 表单等。

现在,假设我们有一个针对 web 商店的 HTTP/JSON API,并且我们想要构建一个 HTML/CSS/JavaScript 客户端,为我们的客户提供优秀的用户体验。让该客户机成为 一般客户机应用程序是一个现实的选择吗?没有。我们希望为每个特定的数据元素和每个特定的应用程序状态提供特定的外观。我们不希望在 API 中包含关于这些表示细节的所有知识,相反,客户机应该定义外观,而 API 应该只携带数据。这意味着客户机具有特定资源元素到特定布局和用户交互的硬编码耦合。

这是否是 HATEOAS 的终结,也是 REST 的终结。

Yes ,因为如果我们将有关 API 的知识硬编码到客户机中,我们就失去了 HATEOAS 的好处: 服务器端的更改可能会破坏客户机。

没有,有两个原因:

  1. “ RESTful”是 API 的属性,而不是客户端的属性。只要有可能,理论上是构建一个提供 API 所有功能的通用客户机,这个 API 就可以称为 RESTful。客户端不遵守规则,这不是 API 的错。通用客户端的用户体验糟糕不是问题。为什么重要的是知道它是 有可能有一个通用的客户端,如果我们 其实没有的通用客户端?这让我想到了第二个原因:
  2. RESTful API 为客户端提供了一个选项,可以选择它们希望变得多么通用,也就是说,它们对服务器端更改的弹性有多大。需要提供良好用户体验的客户端可能仍然能够适应 URI 更改、默认值更改等等。在没有用户交互的情况下执行批处理作业的客户机可能对其他类型的更改具有弹性。

如果你对实际例子感兴趣,看看我的 最好的纸。最后一部分是关于仇恨。您将看到,通过 JAREST,即使是高度交互性和视觉吸引力的客户端也可以很好地适应服务器端的变化,尽管不是100% 。