RESTful API运行时可发现性/ HATEOAS客户端devise
对于我参与的SaaS创业公司,我正在构build一个REST风格的Web API和几个客户端应用程序在不同的平台上使用它。 我想我已经知道API了,但现在我正在转向客户。 正如我一直在阅读关于REST的内容,我发现 REST的一个关键部分是发现 ,但是在两种不同的发现真正含义的解释之间似乎有很多争论:
-
开发人员发现 :开发人员将大量的API详细信息硬编码到客户端,例如资源URI,查询参数,支持的HTTP方法以及他们通过浏览文档并试用API响应发现的其他详细信息。 这种types的发现恕我直言,需要冷静的联系和API版本问题,并导致客户端代码硬耦合到API。 看起来好像使用一个logging良好的RPC集合,这并没有什么好处。
-
运行时发现 – 客户端应用程序本身能够在很less或没有带外信息的情况下找出所需的一切(大概只有API处理媒体types的知识)。链接可能很热。 但是,为了使API非常高效,似乎需要大量的查询参数的链接模板,这使得带外信息变得复杂起来。还有其他的困难,我还没有想到,因为我没有在发展中得到了这一点。 但我喜欢松耦合的想法。
运行时发现似乎是REST的圣杯,但我看到了关于如何实现这样的客户端的小小的讨论。 几乎所有我发现的REST源似乎都假定开发人员发现。 任何人都知道一些运行时发现资源? 最佳实践? 具有真实代码的示例或库? 我正在为PHP客户端(Zend Framework)工作。 Objective-C(iOS)的其他。
鉴于开发人员社区中现有的工具和知识,运行时发现是一个现实的目标吗? 我可以写我的客户端以不透明的方式处理所有的URI,但如何最有效地做到这一点是一个问题,尤其是在低带宽连接上。 无论如何,URI只是等式的一部分。 那么运行时环境中的链接模板呢? 除了提出大量的OPTIONS请求之外,如何沟通支持哪些方法?
在这个video中,Jon Moore使用运行时HATEOAS自动发现来构build一个通用客户端。 这是相当令人印象深刻,值得一看:
http://oredev.org/oredev2010/2010/sessions/hypermedia-apis.html
这绝对是一个坚强的攻坚战。 在谷歌,我们已经实现了我们的发现服务,我们所有的新API都是针对它们而build立的。 TL; DR版本是我们生成的JSON Schema-spec规范,我们的客户可以parsing – 其中许多是dynamic的。
这样的结果意味着开发人员可以更轻松地进行SDK升级,而且对于我们来说,维护更加方便。
绝不是完美的解决scheme,但我们的许多开发人员似乎都喜欢。
请参阅链接了解更多细节(并确保观看video)。
迷人。 你所描述的基本上是HATEOAS原则。 你问什么是HATEOAS? 阅读: http : //en.wikipedia.org/wiki/HATEOAS
通俗地说,HATEOAS意味着链接跟随。 这种方法将您的客户端从特定的URL中分离出来,并让您可以灵活地更改您的API而不会破坏任何人。
你做了你的家庭工作,你到了它的核心:运行时发现是圣杯。 不要追逐它。
UDDI讲述了运行时发现的深刻故事: http : //en.wikipedia.org/wiki/Universal_Description_Discovery_and_Integration
在调用API“RESTful”之前应该满足的一个要求是应该可以在该API之上编写一个通用的客户端应用程序。 对于通用客户端,用户应该能够访问所有API的function。 通用客户端是一种客户端应用程序,它不会假定任何资源具有超出媒体types定义的结构的特定结构。 例如,Web浏览器是知道如何解释HTML的通用客户端,包括HTML表单等。
现在,假设我们有一个网店的HTTP / JSON API,并且我们希望构build一个HTML / CSS / JavaScript客户端,为我们的客户提供出色的用户体验。 让这个客户端成为一个通用的客户端应用程序是否是一个现实的select? 不可以。我们希望为每个特定的数据元素和每个特定的应用程序状态提供一个特定的外观和感觉。 我们不希望在API中包含所有关于这些expression细节的知识,相反,客户端应该定义外观和API,只应该携带数据。 这意味着客户端将特定资源元素与特定布局和用户交互进行硬编码耦合。
这是HATEOAS的结束,因此REST的结束? 是和不是 。
是的 ,因为如果我们将关于API的知识硬编码到客户端,我们就会失去HATEOAS的好处:服务器端的更改可能会破坏客户端。
不 ,有两个原因:
- “RESTful”是API的属性,而不是客户端的属性。 只要理论上可以构build一个提供API所有function的通用客户端,API就可以称为RESTful。 客户不服从规则的事实不是API的错。 通用客户端的用户体验糟糕的事实不是问题。 为什么重要的是要知道,如果我们实际上没有这个通用客户端,就有可能拥有一个通用客户端? 这使我有第二个理由:
- RESTful API为客户提供了select他们想要的通用性的选项,即他们想要的服务器端更改的灵活性。 需要提供良好用户体验的客户端仍然可以对URI更改,默认值更改等进行修改。 在没有用户交互的情况下执行批处理作业的客户可能对其他types的更改具有弹性
如果你对实际案例感兴趣,请查阅我的JAREST论文 。 最后一节是关于HATEOAS。 你会发现,在JAREST中,即使是高度交互式的,视觉上有吸引力的客户端也可以很好地适应服务器端的变化,尽pipe不是100%。
我认为关于HATEOAS的重要一点不是它是客户端的一个圣杯,而是将客户端与URI变化隔离 – 假定您正在使用已知(或开发者发现的定制)链接关系,这将允许系统知道对象的哪个链接是可编辑的表单。 重要的一点是使用超媒体感知的emdiatypes(例如,HTML,XHTML等)。
有关基本运行时发现客户端的另一个示例,请查看HAL Talk超媒体API客户端演示 。
基于超文本应用程序语言(用于链接的XML + JSON模式): http : //stateless.co/hal_specification.html
你写:
为了使API非常高效,似乎需要大量用于查询参数的链接模板,这使得带外信息蠕变回来。
如果该链接模板在前一个请求中提供,则不存在带外信息。 例如,HTMLsearch表单使用链接模板( /search?q=%@
)来生成URL( /search?q=hateoas
),但客户端(Web浏览器)不知道如何使用HTML表单和GET
。