如果RESTful API应该使用HATEOAS,为什么还需要记录文档?

5
为了理解 RESTful API 的基本目的,我已经开始深入研究 HATEOAS
根据维基百科页面所述,
“REST客户端不需要关于如何与任何特定应用程序或服务器进行交互的先前知识,除了对超媒体的通用理解。相比之下,在面向服务的架构(SOA)中,客户端和服务器通过共享文档或接口描述语言(IDL)的固定接口进行交互。”
现在,除非存在有关API中可用内容的先前知识,否则我真的不明白这个应该如何工作,这违背了 HATEOAS 的规定目的。事实上,像 Swagger 这样的工具存在的唯一目的就是记录 RESTful API。
因此,虽然我理解 HATEOAS 可以允许 Web 服务指示资源状态,但我不明白在没有某种“固定接口”的情况下,客户端应用程序可能如何找出如何使用返回的后续链接。

HATEOAS如何实现这一点?

2个回答

10
您有些混淆了。Swagger等工具的存在并不是为了专门记录RESTful API。它们的存在是为了记录那些不符合RESTful标准的HTTP API!对于那些非超文本驱动的API,需要使用这样的工具,并将文档集中在URI语义和方法上,而不是媒体类型。所有那些生成URI列表和HTTP方法的花哨工具都恰恰相反,这与REST的要求完全相反。引用Roy Fielding的话来说:
“REST API应该将几乎所有的描述性工作都花在定义用于表示资源和驱动应用程序状态的媒体类型上,或者在现有标准媒体类型的扩展关系名称和/或超文本启用标记上。任何描述在哪些感兴趣的URI上使用什么方法的努力都应完全在媒体类型的处理规则范围内定义(在大多数情况下,已由现有媒体类型定义)。[在这里失败意味着带外信息正在驱动交互,而不是超文本。]”

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

HATEOAS并不排除所有文档的需求。 HATEOAS使您可以将文档重点放在媒体类型上。您的应用程序应符合底层协议 - 大多数情况下是HTTP - 该协议的权威文档是您的客户端所需的所有内容,以便进行交互。但他们仍然需要知道他们正在与什么进行交互。
例如,当您进入Stack Overflow时,您知道有用户、问题和答案。您需要文档来了解这些东西的确切内容,但您不需要详细的文档来说明单击链接或按钮的操作。您的浏览器已经知道如何驱动它,在其他地方也是如此。

引用另一个答案的话,REST是Web本身的架构风格。当您进入Stack Overflow时,您知道什么是用户、问题和答案,您知道媒体类型,并且网站为您提供链接。REST API也必须这样做。如果我们按照人们认为应该遵循REST的方式设计Web,而不是有一个主页链接到问题和答案,我们将有一个静态文档来解释,为了查看问题,您必须取代id为Question.id并将其粘贴到浏览器上的URI stackoverflow.com/questions/。那是无稽之谈,但那正是许多人认为REST是什么。


我困惑的是,Swagger声称:“Swagger是您的RESTful API的简单而强大的表现形式。”那么他们是错了吗? - MirroredFate
1
我不会说是错误的。REST已经成为任何HTTP API的流行词,如果你在宣传一个产品,说它针对RESTful API是一个很好的营销策略,即使你知道那些真正设计实际RESTful API的人不需要你的产品。这增加了混淆,但现在情况已经无法更糟了。事实上,一些人放弃了REST术语,因为现在不可能扭转这种流行趋势,并将真正的RESTful API称为超媒体API。 - Pedro Werneck
4
我会投票赞同说那些自以为是的人只是错了。也许他们只处于理查森成熟度模型中的第二级。 - Chris DaMour
1
@PedroWerneck 我完全同意!我会时不时地引用这个摘要 :) - sschrass
@ChrisDaMour 我还没有理解为什么那么多人在谈论Richardson成熟度模型与REST的结合。在我看来,这完全是垃圾。首先,从level 3以下根本就没有REST,其次,即使在level 3,也不能保证API实际上遵循了REST的思想。REST是一种将客户端与服务器在分布式系统中解耦的模型,只做一半工作并不能达到这个目标。在我的观点中,这是一种全面的方法,虽然初始开销高,但一旦实施,维护开销就会很低。 - Roman Vottner
@RomanVottner,是的,我同意你的看法。但是这个模型很好,因为它让那些不理解的人看到自己在某个层次上的位置,并希望打开他们所缺失的门。我花了一些时间谈论成熟度模型为什么有用,链接是https://youtu.be/u_pZBBELeEQ?t=462。我只专门谈论了级别3的RESTful,以及REST API如何被恶意篡改。 - Chris DaMour

3
这个问题的答案因客户端与服务交互的自主级别而异... 首先让我们看看人类驱动的客户端 - 浏览器。浏览器对银行、音乐会、猫和网络上其他任何东西一无所知,但它肯定知道如何呈现HTML。HTML是一种支持超媒体(链接和表单)的媒体类型。在这种情况下,您有一个完全工作的应用程序,其客户端只理解通用超媒体。这里的“固定界面”是HTML。
然后我们有自主客户端或“脚本化”客户端,这些客户端应该在没有人类干预的情况下与服务交互。当将REST与SOA(P)进行比较时,这可能是您考虑的客户端类型。您可以在两个独立的计算机系统之间交换数据的集成场景中找到此类客户端。
这样的自主客户端必须确实就某些事情达成一致才能相互交互。问题是这个“某些事情”是什么或不是什么。
在面向服务的架构中,客户端同意特定的URL /端点和特定的“方法”在这些端点上调用(RPC) - 这增加了使用的URL结构的耦合性。它还强制客户端知道在哪个服务上调用哪个方法 - 服务器无法更改URL,也无法将“方法”从一个服务移到另一个服务而不破坏客户端。
REST /超媒体基础系统的行为方式不同。在这种系统中,客户端和服务器同意一个通用入口URL,在其中客户端可以在运行时查找(GET)服务文档,描述使用超媒体控件(如链接或表单)与服务器进行所有可能交互的方式。这些超媒体控件向客户端提供有关如何与服务进行交互(HTTP方法和有效负载编码)以及在哪里与服务进行交互的信息。本质上意味着我们不再拥有“一个服务”,而可能有许多不同的服务,因为客户端将在运行时被告知在哪里以及如何与它们进行交互。
那么客户端如何知道应该查找哪些超媒体控件?它通过同意一组标识符来完成,服务器将使用这些标识符来标识相关控件。对于链接,这通常称为“链接关系类型”。
这使我们得出了服务器和客户端达成一致的“某些事情”的类型 - 它是1)启用超媒体的媒体类型,2)根服务索引URL,3)超媒体控件标识符和4)每个控件预期的有效负载。在运行时,客户端然后发现剩余的URL、HTTP方法和有效负载编码(如JSON、XML或URL编码的键/值对)。
目前,有一小组通用超媒体API媒体类型 - Mason、HAL、Sirene、Collection JSON、Hydra用于JSON-LD,可能还有其他几个。
如果您感兴趣,我在各种博客文章中都涵盖了这个话题。

我非常感激这个解释——我认为它很好地解释了HATEOAS的目的。 - MirroredFate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接