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

Why document RESTful APIs if they are supposed to use HATEOAS?

为了掌握 RESTful API 的潜在目的,我开始深入研究 HATEOAS

根据该维基百科页面,

A REST client needs no prior knowledge about how to interact with any particular application or server beyond a generic understanding of hypermedia. By contrast, in a service-oriented architecture (SOA), clients and servers interact through a fixed interface shared through documentation or an interface description language (IDL).

现在,我真的不明白它应该如何工作,除非事先了解 API 中可用的内容,这与 HATEOAS 的既定目的背道而驰。事实上,诸如 Swagger 之类的工具的存在就是为了明确记录 RESTful APIs.

所以虽然我知道 HATEOAS 可以允许 Web 服务指示资源的状态,但我错过了 link(哈哈)演示客户端应用程序如何可能弄清楚要做什么在没有某种 "fixed interface".

的情况下处理返回的后续 links

HATEOAS 应该如何做到这一点?

根据与服务交互的客户端的自主级别,这个问题有多种答案...

让我们首先看一下人类驱动的客户端——浏览器。浏览器对银行、音乐会、猫以及您在网上找到的任何其他内容一无所知 - 但它肯定知道如何呈现 HTML。 HTML 是一种支持超媒体(链接和表单)的媒体类型。在这种情况下,您有一个完美运行的应用程序,其客户端只理解通用超媒体。这里的"fixed interface"是HTML.

然后我们有自主客户端或 "scripted" 客户端,它们应该在没有人工交互的情况下与服务交互。在将 REST 与 SOA(P) 进行比较时,您可能会想到这种客户端。您可以在两个独立的计算机系统以某种预定义方式交换数据的集成场景中找到此类客户端。

这样的自治客户端必须就某事达成一致,才能相互交互。问题是这个 "something" 是什么或不是什么。

在面向服务的体系结构中,客户端同意特定 URLs/endpoints 和特定 "methods" 调用这些端点 (RPC) - 这增加了所用 URL 结构的耦合。它还强制客户端知道调用哪个服务的方法 - 服务器不能更改 URLs 并且它不能在不破坏客户端的情况下将 "method" 从一个服务移动到另一个服务。

基于

REST/hypermedia 的系统表现不同。在这样的系统中,客户端和服务器同意一个公共条目 URL,其中客户端可以在运行时查找 (GET) 服务文档,描述使用超媒体控件(例如链接或表单)与服务器的所有可能交互。这些超媒体控件通知客户端 如何 与服务交互(HTTP 方法和负载编码)以及 何处 与服务交互。这实质上意味着我们不再有 "a service",但可能会有许多不同的服务,因为客户端将在运行时被告知,在何处以及如何与它们进行交互。

那么客户端如何知道它应该寻找哪个超媒体控件呢?它通过就一组标识符达成一致,服务器将使用这些标识符来识别相关控件。对于链接,这通常称为 "link relation types".

这让我们知道服务器和客户端同意哪种 "something" - 它是 1) 支持超媒体的媒体类型,2) 根服务索引 URL,3)超媒体控件标识符和 4) 每个控件预期的有效负载。在运行时,客户端会发现剩余的 URLs、HTTP 方法和负载编码(例如 JSON、XML 或 URL 编码的 key/value 对)。

目前有一小部分用于超媒体 API 的通用媒体类型 - Mason、HAL、Sirene、Collection JSON、JSON-LD 的 Hydra,可能还有更多。

如果您有兴趣,那么我已经在各种博客文章中介绍了这个主题:

你把事情弄糊涂了。像 Swagger 这样的工具不存在用于记录 RESTful APIs 的明确目的。它们的存在的明确目的是记录不是 RESTful 的 HTTP API!您需要像 API 这样的工具,它们不是超文本驱动的,并且将文档重点放在 URI 语义和方法上而不是媒体类型上。所有那些生成 URI 和 HTTP 方法列表的奇特工具与您在 REST 中应该做的完全相反。引用 Roy Fielding 的话:

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]

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

HATEOAS 并不排除对所有文档的需求。 HATEOAS 允许您将文档集中在您的媒体类型上。您的应用程序应该符合底层协议——大多数情况下是 HTTP——并且关于该协议的权威文档是您的客户驱动交互所需要的全部。但他们仍然需要知道他们正在与什么互动。

比如,当你进入Stack Overflow,你就知道有用户,有问题,有答案。您需要有关这些东西到底是什么的文档,但不需要详细说明单击 link 或按钮的作用的文档。您的浏览器已经知道如何驱动它,这就是它在其他地方的工作方式。

引用 another answer,REST 是 Web 本身的架构风格。当你进入 Stack Overflow 时,你知道什么是用户、问题和答案,你知道媒体类型,并且网站为你提供了 links 给他们。 REST API 必须做同样的事情。如果我们按照人们认为 REST 应该完成的方式设计网络,而不是有一个带有 links 的问题和答案的主页,我们会有一个静态文档来解释为了查看问题,你有获取 URI whosebug.com/questions/,将 id 替换为 Question.id 并将其粘贴到您的浏览器中。这是胡说八道,但很多人认为 REST 就是这样。