被大肆宣传的REST API只是一个http方法加上HATEOAS链接吗?

时间:2019-05-18 11:35:00

标签: rest http

我读到HATEOAS链接是将REST API与常规http API分开的链接。在这种情况下,REST是否需要一个单独的名称?我不知道有关REST API的所有宣传是什么。它似乎只是一个http方法,在响应中有一个额外的规则。 问)还有什么其他区别?

2 个答案:

答案 0 :(得分:3)

  

我读到HATEOAS链接是将REST API与常规http API分开的链接。

这可能有点轻描淡写。当Leonard Richardson (2008)描述网络的“技术堆栈”时,他列出了:

  • URI
  • HTTP
  • HTML

探索后者的一种方法是考虑HTML(作为一种媒体类型)与其中带有URI的文本文档有何不同。在我看来,关键要素是链接和形式-标准化URI的语义表示形式的标准化方法(这是指向另一页的链接,这是嵌入式图像,这是一个嵌入式脚本,这是一种形式...)。

Mike Admundsen,2010年:

  

超媒体类型是MIME媒体类型,其包含导致应用程序流的本机超链接语义。例如,HTML是一种超媒体类型。 XML不是。

Atom Syndication / Atom Publishing是定义REST API的很好演示。

  

您能否阐明REST的真正含义以及它与普通http有何不同?

您是否注意到网站通常不使用纯文本来表示它们所共享的信息?这是一个死胡同-原始文本没有内置任何超媒体语义,因此,通用客户端除了搜索可能是URI的序列之外,不会做其他有趣的事情。

另一方面,对于HTML,我们具有链接语义:我们可以包括对图像,样式表,脚本的引用,以及对其他文档的链接。我们可以描述允许创建参数化HTTP请求的表单。

此外,这意味着如果客户端不应该使用某些关系,则服务器可以轻松地更改表示形式以删除链接。

此外,超媒体表示的使用允许服务器使用更丰富的描述来说明客户端应发送哪个请求消息。

例如,考虑Google。他们可以使用表格来控制搜索请求是使用GET还是POST。他们可以删除“我觉得很幸运”选项,或安排将其重定向到主要体验。他们可以将其他信息嵌入到表单的字段中,以跟踪发生的情况。他们可以选择在搜索结果中使用哪些URI目标,从而指示客户端将另一个请求重定向至实际目标,并将其附加到查询参数中的其他元数据发送给Google,而所有其他元数据都嵌入了查询参数中,而无需与客户端使用

有关进一步的讨论,请参阅伦纳德·理查森(Leonard Richardson)的slide deck from QCon 2008或菲尔·斯特金(Phil Sturgeon)的REST and Hypermedia in 2019

  

如果HATEOAS链接是POST API,是否认为客户不需要阅读文档? HATEOAS链接将仅引导您使用API​​,但不会对如何填充其请求正文进行任何说明。...GET将没有请求正文。因此,没有太多问题。但是POST API?

-的排序-这里是Fielding writing in 2008

  

REST并不能消除线索。 REST所做的就是将对先验知识的需求集中到易于标准化的形式中。

在网络上,常见的用例是协助人类的代理商;人类可以自行解决某些歧义。结果是责任分离;人类对消息的特定领域语义进行解码,客户端确定将交互描述为HTTP请求的正确方法。

如果我们想轻松地用机器代替人,那么我们将需要在消息模式中投入额外的设计资金,该消息模式必须像表达管道一样清楚地表达特定于领域的语义。

答案 1 :(得分:0)

对我来说,REST是一种您要针对的意识形态,如果您拥有一个可以持续多年的系统,并且该系统可以自由发展而又不会破坏您无法控制的部件。这与Web非常相似,在Web中,服务器无法直接控制浏览器,尽管浏览器能够配合服务器返回的网站表示所做的任何更改。

  

我读到HATEOAS链接是将REST API与常规http API分开的链接。在这种情况下,REST是否需要一个单独的名称?

REST基本上可以实现其名称所暗示的功能,它可以传输资源表示的状态。如果是这样,我们应该为此类“ REST” API命名一个新的名称,以防混淆。

如果您通读Richardson Maturity Model (RMM),则可能会感到这样的印象,即Fowler命名的链接或超媒体控件(在第3层是必需的)是将REST与常规HTTP交互分开的功能。但是,第3级仅不足以实现去耦的最终目标。

大多数所谓的“ REST API”确实将大量设计工作投入到漂亮的URI中,以向客户端开发人员表达目标资源的含义。他们提供了由其工具支持生成的精美文档,例如Swagger或类似内容,客户端开发人员必须严格遵循这些文档,否则他们将无法与API进行交互。这类API是RPC。您将无法指向与API A交互的同一客户端现在指向API B,并且仍然可以立即使用,因为它们可能使用完全不同的终结点并为几乎相同的命名资源终结点返回不同类型的数据。尝试使用更多动态行为的客户端可能会通过解析端点来学习类型,并期望诸如.../api/users之类的URI返回用户,而此时突然间,API将其URI结构更改为某种形式像.../api/entities。现在会发生什么?这些客户端中的大多数都会中断,这清楚地表明整个交互模型没有遵循REST架构的概述。

REST强调链接关系名称,该名称应该允许客户端随时间实际变化,从而为客户端提供一种稳定的学习URI意图的方式。 URI基本上附加到链接关系名称上,并且基本上表示可负担性,这很清楚它的作用。即一个按钮的承受能力可能是您可以按下它,结果会发生一些事情。否则,电灯开关的作用就是根据电灯开关的切换状态打开或关闭灯。

链接关系名称现在表达了这种承受能力,并且是一种基于文本的方式来表示网页上表项旁边的诸如垃圾桶或铅笔符号之类的东西,如果您可能会发现单击某项将删除其中的一项表格,而另一个符号则允许编辑该条目。此类链接关系名称应为standardized,使用widely accepted ontologies或使用custom link-relation extensions as outlined by RFC 8288 (Web Linking)

但是,请务必注意,URI只是不应该向客户端传达语义的URI。这并不意味着URI不能对服务器或API具有语义,但是客户端不应尝试从URI本身推论出URI。这就是链接关系名称的含义,它提供了该关系的不经常更改的部分。端点可能被多个不同的URI引用,其中一些URI可能使用用于过滤的不同查询参数。根据Fielding,这些URI分别代表不同的资源:

  

REST中的资源定义基于一个简单的前提:标识符应尽可能少地更改。因为Web使用嵌入式标识符而不是链接服务器,所以作者需要一个标识符,该标识符与超媒体引用所期望的语义紧密匹配,即使访问该引用的结果可能随时间变化,该引用也可以保持静态。 REST通过将资源定义为作者打算识别的语义,而不是创建引用时与这些语义相对应的值来实现此目的。然后留给作者以确保为参考选择的标识符确实标识了预期的语义。 (来源6.2.1

由于URI用于缓存结果,因此它们基本上表示用于缓存响应有效负载的键。这样,很明显,在向GET请求中使用的URI添加其他查询参数时,您最终绕过了缓存,因为密钥尚未存储在缓存中,因此即使获得了不同资源的结果,如果没有其他参数,它可能与URI相同(也在响应表示中)。

  

我想知道有关REST API的所有宣传是什么。它似乎只是一个http方法,在响应中有一个额外的规则。

简而言之,这就是那些自称为市场营销的伪“ REST API”所传达的含义,而且许多人似乎也了解。

“ REST”的大肆宣传源于开发人员与其他互操作解决方案(例如Corba,RMI或SOAP)进行交互时所带来的不便,在这些交互解决方案中,通常必须使用部分商业的第三方库和框架才能与之交互这样的系统。大多数语言都直接支持HTTP作为客户端和服务器,从而消除了对外部库或框架本身的要求。除此之外,基于RPC的解决方案通常需要首先生成某些存根或骨架类,这通常是由构建管道自动完成的。在更新IDL(例如WSDL链接或包括XSD模式)后,需要重做整个存根生成,并仔细检查整个代码以发现是否添加了重大更改。通常没有明显的变更日志可供使用,这使更改或更新此类内容成为...的痛苦。

在这些伪“ REST” API中,纯JSON现在几乎已经成为事实上的标准,避免了生成存根类的步骤以及避免分析自己的代码以查看某些强制性更改是否对代码产生负面影响的麻烦。系统。这些API中的大多数都使用某种基于URI的版本控制,从而使开发人员可以根据URI来了解是否引入了某些破坏性的东西,模仿了semantic versioning

这些解决方案的问题在于,不是响应表示格式本身已被版本化,而是整个API本身导致了常见问题,当仅应对API的一部分进行更改时,因为现在整个API的版本都需要被撞。除此之外,诸如.../api/v1/users/1234.../api/v2/users/1234之类的URI可能代表同一用户,因此同一资源尽管实际上因URI不同而实际上是不同的。

  

Q)还有什么其他区别?

尽管REST只是一个架构模型,不能强迫您严格执行它,但是如果忽略其中的某些constraints,您将无法从其属性中受益。如上所述,因此,HATEOAS支持还不足以真正使所有客户端与API脱钩,因此无法从REST体系结构中受益。

不幸的是,

RMM根本没有谈论媒体类型。媒体类型基本上指定了应如何处理收到的有效负载,并定义了该有效负载内使用的每个元素的语义和约束。即如果您查看在text/html中注册的IANA's media type registry,您会发现它指向published specification,它始终引用HTML的最新版本。 HTML的设计方式可保持向后兼容,因此不需要特殊的版本控制内容。

IMO向HTML提供了两个重要的内容:

前一种允许结构化数据,使某些段或元素可以表达在媒体类型中定义的不同语义。即浏览器对图片的处理方式不同于div元素或article元素。搜寻器可能更喜欢article元素中包含的链接和内容,而完全忽略脚本和图像元素。根据某些元素的存在或不存在,甚至可能发生某些处理差异。

在REST中实际上包括对表单的支持是非常重要的事情,因为这是允许服务器向客户端教授服务器需要什么作为输入的功能。大多数所谓的“ REST API”只是迫使开发人员仔细阅读其文档(可能已过时,不正确或不完整),并根据文档将数据发送到预定义的端点。如果文档过时或不完整,客户端应该如何能够将数据发送到服务器?而且,服务器可能永远无法更改,因为基本上文档已经成为事实,API必须与文档保持一致。

不幸的是,表单支持还处于起步阶段。除了提供<form>...</form>的HTML外,您还有几种基于JSON的表单尝试,例如hal-formshalo-json (halform)Ionhydra。这些都还没有广泛的库或框架支持,因为其中一些表单表示形式尚未最终确定如何更有效地支持表单的规范。

不幸的是,尽管其他媒体类型通常对REST仍然很有价值,但它们可能不使用半结构化内容或不提供对可根据服务器需求教客户的形式的支持。首先,可以通过Web linking链接支持添加到自然不支持的媒体类型。其次,数据本身实际上完全不需要基于文本即可使应用程序进一步使用它。即图片通常是对视频进行编码和基于字节的,但客户端仍然可以将其呈现给用户。

关于媒体类型的主要观点是,正如菲尔丁(Fielding)在他引用的一篇博客文章中pointed out所说的那样,不应将表示与类型混淆。菲尔丁说:

  

REST API永远不应具有对客户端重要的“类型化”资源。规范作者可以使用资源类型来描述接口背后的服务器实现,但是这些类型对于客户端而言必须是不相关且不可见的。对客户来说唯一重要的类型是当前代表的媒体类型和标准化的关系名称。

JørnWildt在一篇出色的博客文章中解释了"typed" resource是什么,以及为什么REST体系结构不应该使用此类类型。基本上,总而言之,如果服务器添加其他意外字段,重命名现有字段或忽略预期字段,则期望../api/users端点返回预先假定的数据有效负载的客户端可能会中断。可以通过使用简单的content-type negotiation来避免这种耦合,其中客户端通知服务器客户端支持的功能,并且客户端将选择最适合目标资源的表示形式。如果服务器不能通过表示支持客户端,则客户端支持服务器应该以失败(或默认表示)响应,客户端可能会记录下来以通知用户。

从本质上讲,这正是REST所代表的名称,即资源状态表示的传输,其中表示可能会有所不同,具体取决于所选媒体类型定义的表示格式。尽管HATEOAS可能是REST和基于非REST的HTTP解决方案之间最明显的变化之一,但可以肯定的是,这并不是构成REST负载的唯一因素。我希望我能对解耦的意图有所了解,并且服务器应该通过格式告诉客户服务器期望的形式,并且URI的提供是通过链接关系名称捕获的。总而言之,所有这些微小的方面都构成了REST,不幸的是,如果您尊重REST的所有约束,并且不仅是那些容易获得的约束,或者是您有意实施的约束,那么您将仅从REST中受益。