简体   繁体   English

REST API OPTIONS 可以用作 HATEOAS 唯一的请求吗?

[英]Could REST API OPTIONS be used as the HATEOAS only request?

As I've understood it, REST MUST use the HATEOAS constraint to be implemented properly.据我了解,REST 必须使用 HATEOAS 约束才能正确实施。 My understanding of HATEOAS is that basically every resource should share information about what communication options it has and how the consumer can use those options to achieve their end goal.我对 HATEOAS 的理解是,基本上每个资源都应该共享有关其具有哪些通信选项以及消费者如何使用这些选项来实现其最终目标的信息。

My question is if the HTTP OPTIONS method could be used as a way to navigate a REST API.我的问题是是否可以使用 HTTP OPTIONS 方法来导航 REST API。 Basically the response from an OPTIONS request would include the possible actions to take on a resource which would make it possible to consume the API without knowing the endpoints.基本上,来自 OPTIONS 请求的响应将包括对资源采取的可能操作,这将使在不知道端点的情况下使用 API 成为可能。

eg An initial request to the API例如对 API 的初始请求

HTTP OPTIONS /api

Could return all resources available for consumption and their relations.可以返回所有可供消费的资源及其关系。 Like a massive tree to consume the API and all it has to offer.就像一棵巨大的树来消耗 API 和它所提供的一切。 This idea doesn't neglect implementing HATEOAS on other responses as well, but the OPTIONS request would allow navigation without returning data that the consumer might not actually want to consume.这个想法也没有忽略在其他响应上实现 HATEOAS,但是 OPTIONS 请求将允许导航而不返回消费者可能实际上不想使用的数据。

Is this a really bad idea?这真的是个坏主意吗? Or is it something that is commonly implemented.或者它是通常实施的东西。 I'm currently attempting to implement a REST API but I'm having a hard time understanding the benefit of HATEOAS if there is no way to navigate the API without actually requesting data that you might not necessarily need when consuming certain end points.我目前正在尝试实现 REST API 但如果没有办法导航 API,您可能不一定需要在没有实际请求的情况下消耗某些端点数据时,我很难理解 HATEOAS 的好处。 And I assume HATEOAS aims to make clients consume resources by their relation and not actually hard coding the end point?而且我认为 HATEOAS 旨在让客户通过他们的关系来消耗资源,而不是实际上对端点进行硬编码?


TL;DR TL;博士

Could HTTP OPTIONS request act as a way to navigate a REST API by returning what communication options are available for the requested resource without actually returning the resource? HTTP OPTIONS 请求是否可以作为导航 REST API 的方式,通过返回哪些通信选项可用于请求的资源而不实际返回资源?

According to RFC 7231根据RFC 7231

The OPTIONS HTTP method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. OPTIONS HTTP 方法在源服务器或中间中介请求有关目标资源可用通信选项的信息。 This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action.此方法允许客户端确定与资源相关联的选项和/或要求,或服务器的能力,而无需暗示资源操作。

... ...

A server generating a successful response to OPTIONS SHOULD send any header fields that might indicate optional features implemented by the server and applicable to the target resource (eg, Allow), including potential extensions not defined by this specification.生成对 OPTIONS 的成功响应的服务器应该发送任何 header 字段,这些字段可能指示服务器实现并适用于目标资源的可选功能(例如,允许),包括本规范未定义的潜在扩展。 The response payload, if any, might also describe the communication options in a machine or human-readable representation.响应有效负载(如果有)也可能以机器或人类可读表示形式描述通信选项。 A standard format for such a representation is not defined by this specification, but might be defined by future extensions to HTTP.本规范未定义此类表示的标准格式,但可能由 HTTP 的未来扩展定义。 A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in the response.如果没有在响应中发送有效载荷主体,服务器必须生成值为“0”的 Content-Length 字段。

So, basically a response to an OPTIONS request will tell your client which HTTP operations may be performed on a certain resource.因此,基本上对 OPTIONS 请求的响应将告诉您的客户端哪些 HTTP 操作可以在某个资源上执行。 It is furthermore admissible to target the whole server on utilizing * instead of a specific resource URI.此外,可以使用*而不是特定的资源 URI 来定位整个服务器。

A response to an OPTIONS request may look like this:对 OPTIONS 请求的响应可能如下所示:

HTTP/1.1 204 No Content
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1

which states that a certain resource supports the mentioned operations in the Allow header of the resonse.其中指出某个资源支持响应的Allow header 中提到的操作。 Via the Cache-Control header a client knows that it by default can cache responses of safe requests (GET and HEAD) for up to 7 days (value is mentioned in seconds).通过Cache-Control header,客户端知道默认情况下它可以缓存安全请求(GET 和 HEAD)的响应长达 7 天(以秒为单位提及值)。 The x-ec-custom-error header specifies a non-standard header that is specific to a particular software, in that particular case to a ECS Server . x-ec-custom-error header 指定了特定于特定软件的非标准 header,在这种特定情况下,特定于ECS 服务器 According to this Q & A the meaning isn't publicly documented and therefore application specific.根据此问答,其含义未公开记录,因此特定于应用程序。

In regards to returning a tree of traversable resources from the given resource the OPTIONS operation was requested for, technically this could be possible, however, certain systems might produce an almost never-ending list of URIs.关于从请求 OPTIONS 操作的给定资源返回可遍历资源树,从技术上讲这是可能的,但是,某些系统可能会产生几乎永无止境的 URI 列表。 Therefore such a design is questionable for larger systems.因此,这样的设计对于更大的系统是有问题的。

My understanding of HATEOAS is that basically every resource should share information about what communication options it has and how the consumer can use those options to achieve their end goal.我对 HATEOAS 的理解是,基本上每个资源都应该共享有关其具有哪些通信选项以及消费者如何使用这些选项来实现其最终目标的信息。

Hypertext as the engine of application state (HATEOAS) is basically just a requirement to use the interaction model used on the Web for decades quite successfully and offer the same functionality to applications.超文本作为应用程序 state (HATEOAS) 的引擎基本上只是使用 Web 上使用的交互 model 的要求,几十年来相当成功地为应用程序提供相同的功能。 This enabled applications to surf the Web similar like we humans do.这使应用程序能够像我们人类一样浏览Web。

Great, but how does it work?很好,但它是如何工作的?

On the Web we use links and Web forms all the time.在 Web 上,我们一直使用链接和Web forms Through a Web form a server is able to teach a client basically what properties a certain resource supports or expects.通过 Web 表格,服务器能够基本上教客户端某个资源支持或期望的属性。 But that's not all, The same form also tells your client where to send the request to (target URI), the HTTP method to use and, usually implicitly given.但这还不是全部,相同的表单还告诉您的客户端将请求发送到哪里(目标 URI),使用 HTTP 方法,通常是隐式给出的。 the media type the payload needs to be serialized to upon sending the request to the server, This, in essence.在将请求发送到服务器时,有效负载需要序列化的媒体类型,本质上是这样。 makes out-of-band API documentation unnecessary as all the information a client needs to make a valid request is given by the server already.不需要带外 API 文档,因为客户端发出有效请求所需的所有信息都已由服务器提供。

On a typical Web site you might have a table of entries which offers the option to add new entries, update or delete existing ones.在典型的 Web 站点上,您可能有一个条目表,其中提供了添加新条目、更新或删除现有条目的选项。 Usually such links are hidden behind fancy images, ie a dustbin for deleting an entry and a pencil for editing an existing entry or the like where the image represents an affordance.通常这些链接隐藏在精美的图像后面,即用于删除条目的垃圾箱和用于编辑现有条目的铅笔等,其中图像表示可供性。 The affordance of certain elements make it clear what you should do with it or what's the purpose of that element.某些元素的可供性清楚地表明您应该用它做什么或该元素的目的是什么。 A button on a page wants to be pushed while a slider widget wants to be changed while a text field waits for user input.当 slider 小部件想要更改时,页面上的按钮想要被按下,而文本字段等待用户输入。 As applications aren't that eager to work on images a further concept is used instead.由于应用程序并不急于处理图像,因此使用了进一步的概念。 Link relation names exactly serve this purpose.链接关系名称正是用于此目的。 Ie if you have a pageable collection consisting of multiple page à 25 entries ie you might be familiar with a widget containing arrows to page through that collection.即,如果您有一个由多个页面à 25 个条目组成的可分页集合,即您可能熟悉包含用于翻阅该集合的箭头的小部件。 A link here should usually be annotated with link relation names such as self , next , prev , first or last .此处的链接通常应使用链接关系名称进行注释,例如selfnextprevfirstlast The purpose of such links is quite clear, some others like prefetch , that indicates that a resource can be loaded in the background early as it is very likely that the next action may request it, might be less intuitive at first.此类链接的目的非常明确,其他一些例如prefetch ,表示可以在后台尽早加载资源,因为很可能下一个操作可能会请求它,一开始可能不太直观。 Such link relation names should be standardized or at least follow the Web Linking extension mechanism .此类链接关系名称应标准化或至少遵循Web 链接扩展机制

Through the help of link-relation names a client that knows to look for URIs annotated with next ie will still work if the server decides to change its URI scheme as it treats the URI rather opaque.通过链接关系名称的帮助,如果服务器决定更改其 URI 方案,因为它认为 URI 相当不透明,知道查找带有next ie 注释的 URI 的客户端仍然可以工作。

Of course, both client and server need to support the same media type that furthermore is able to represent such capabilities.当然,客户端和服务器都需要支持相同的媒体类型,并且能够代表这种能力。 Plain application/json is ie not able to provide such a support.普通的application/json即无法提供这样的支持。 HAL JSON or JSON Hyper-Schema at least add support for links and link relation names to JSON based documents, while hal-forms , halo+json (halform) and ion might be used to teach a client how a request needs to be created. HAL JSON or JSON Hyper-Schema at least add support for links and link relation names to JSON based documents, while hal-forms , halo+json (halform) and ion might be used to teach a client how a request needs to be created. The question here shouldn't be which media type to support but how many different ones you want to support as the more media types your API is able to handle, the more likely it will be to interact with arbitrary clients not under your control.这里的问题不应该是支持哪种媒体类型,而是要支持多少不同的媒体类型,因为 API 能够处理的媒体类型越多,与不受您控制的任意客户端交互的可能性就越大。

These concepts allow you to basically use the controls given in the server response to "drive your workflow" forward.这些概念允许您基本上使用服务器响应中给出的控件来“推动您的工作流程”向前发展。 In essence, what you, as an API designer should do is to design the interactions of a client with your API so that it follows a certain, as Jim Webber termed it, domain application protocol or state machine as Asbjørn Ulsberg put it that basically guides a client through its task, ie ordering from your shop API.本质上,作为 API 设计师应该做的是设计客户端与您的 API 的交互,以便它遵循特定的,正如 Jim Webber 所说的那样,域应用程序协议Z9ED39E2EA931586B36A985A6942EF5 基本上是机器指导客户通过其任务,即从您的商店订购 API。

So, in short, HATEOAS is comparable to Web surfing for applications by making use of named link relations and form-like media type representations that allow you to take actions solely on the response retrieved from a server directly instead of having to bake external knowledge stemming from some reference documentation page (Swagger, OpenAPI or the like) into your application.因此,简而言之,HATEOAS 与 Web 相当从一些参考文档页面(Swagger、OpenAPI 等)到您的应用程序。


But how does HATEOAS benefit the consumer in practice then?但是,HATEOAS 在实践中如何使消费者受益呢?

First, it does not have to consult any external documentation other maybe than the current media type specification, though usually support for well-known media types is already backed into popular frameworks or at least allows to add support through plugins or further libraries.首先,除了当前的媒体类型规范之外,它不需要参考任何外部文档,尽管通常对知名媒体类型的支持已经被流行的框架支持,或者至少允许通过插件或其他库添加支持。 Once the media type is understood and supported interactions with all serivces that also support the same media type is possible, regardless of their domain.一旦媒体类型被理解和支持,与同样支持相同媒体类型的所有服务的交互是可能的,无论它们的域如何。 This allows to reuse the same client implementation to interact with service A and service B out of the box.这允许重用相同的客户端实现来与服务 A 和服务 B 进行开箱即用的交互。 In an RPC-like systems you'd need to integrate the API of service A first and if you want to interact with service B also you need to integrate those API separately.在类似 RPC 的系统中,您需要首先集成服务 A 的 API,如果您想与服务 B 交互,还需要单独集成这些 API。 It's most likely that these APIs are incompatible and thus don't allow the reusage of the same classes.这些 API 很可能是不兼容的,因此不允许重用相同的类。

Without knowing the URL for a resource, is the idea that the consumer can discover it by browsing the API, but they will still have a hard dependency on the actual URL?在不知道资源的 URL 的情况下,消费者是否可以通过浏览 API 来发现它,但他们仍然对实际的 ZE6B391A8D2C4D45902A23A8B658D5703 有硬依赖? Or is HATEOAS purpose to leverage actions on a certain resource, ie the consumer knows the users end-point but he does not need to know the end-points for actions to take on the users resource cause those are provided by the API?还是 HATEOAS 的目的是利用对某个资源的操作,即消费者知道用户的端点,但他不需要知道对用户资源采取的操作的端点,因为这些是由 API 提供的?

A client usually does not care about the URI itself, it cares about the content a URI may provide.客户端通常不关心 URI 本身,它关心 URI 可能提供的内容。 Compare this to your typical browsing behavior.将此与您的典型浏览行为进行比较。 Do you prefer a meaningful text that summarizes that links content so you can decide whether to request that resource or do you prefer parsing and dissecting a URI to learn what it might do?您更喜欢有意义的文本来总结链接内容,以便您可以决定是否请求该资源,或者您更喜欢解析和剖析 URI 以了解它可能会做什么? Minifying or obfuscating URIs will do you no favor in the latter case though.不过,在后一种情况下,缩小或混淆 URI 对您没有好处。

A further danger arise from URIs and resources that a client put meaning to.客户端赋予其意义的 URI 和资源会产生进一步的危险。 A slopy developer will interpret such URIs/resources and implement a tiny hack to interact with that service assuming the URI/resource will remain static.一个草率的开发人员会解释这样的 URI/资源并实施一个小技巧来与该服务交互,假设 URI/资源将保持 static。 Ie it is not unreasonable to consider a URI /api/users/1 to return some user related data and based on the response format a tiny Java class is written that expects to receive a field for username and one for email ie.即考虑使用 URI /api/users/1返回一些与用户相关的数据并根据响应格式编写一个微小的 Java class 并期望接收用户名字段和 Z0C83F57C786A7EB2 字段是合理的。 If the server now decides to add additional data or rename its fields, the client suddenly will not be able to interact with that service further.如果服务器现在决定添加其他数据或重命名其字段,客户端将突然无法与该服务进一步交互。 And rest assured that in practice, especially in the EDI domain, you will have to interact with clients that are not meant to interact with the Web or where programmers implemented their own JSON framework that can't coope with changing orders of elements or can't handle additional optional fields, even though the spec contains notes on those issues. rest 保证在实践中,尤其是在 EDI 域中,您将不得不与不打算与 Web 交互的客户端交互,或者程序员实现自己的 Z0ECD11C1D7A287401D148A287401D148A287401D148A287401D148A287401D148A287401D148A287401D148A287401D148A287401D148A288B2A62AFCZ t 处理额外的可选字段,即使规范包含有关这些问题的说明。 Fielding claimed that菲尔丁声称

A REST API should never have “typed” resources that are significant to the client. REST API 不应该有对客户很重要的“类型化”资源。 Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client.规范作者可以使用资源类型来描述接口背后的服务器实现,但这些类型必须与客户端无关且不可见。 The only types that are significant to a client are the current representation's media type and standardized relation names.对客户端重要的唯一类型是当前表示的媒体类型和标准化关系名称。 [ditto] ( Source ) [同上]( 来源

Instead of typed resources content type negotiation should be used to support interoperability of different stackholders in the network.应该使用内容类型协商来支持网络中不同堆栈持有者的互操作性,而不是类型化资源

As such, the URI itself is just the identifier of a resource that is mainly used to learn where to send a request to.因此,URI 本身只是资源的标识符,主要用于了解将请求发送到何处。 Through the help of meaningful link relation names a client should know that it is interested in ie http:/www.acme.com/rel/orders if it wants to send an order to the service and just looks up the URI that either is annotated with that Web Linking extension realtion name or that has an URI attached to it.通过有意义的链接关系名称的帮助,客户端应该知道它对http:/www.acme.com/rel/orders感兴趣,如果它想向服务发送订单并且只查找被注释的 URI使用该 Web 链接扩展名或附加了 URI。 Whether the link relation name is just an annotation (ie a further attribute on the URI element) or the URI being attached to the link-relation name (ie as an embedded object of the link relation name) is dependent on the actual media type.链接关系名称只是一个注释(即 URI 元素上的进一步属性)还是附加到链接关系名称的 URI(即作为链接关系名称的嵌入 object)取决于实际的媒体类型。 This way, if a server ever decides to change its URI scheme or move around resources, for whatever reason, the client will still be able to find the URI that way and it couldn't care less about the characters present in the URI or not.这样,如果服务器决定更改其 URI 方案或移动资源,无论出于何种原因,客户端仍然能够以这种方式找到 URI,并且它不会关心 URI 中是否存在字符. It just treats the URI as opaque thing.它只是将 URI 视为不透明的东西。 The nice thing here is, that a URI can be annotated with multiple link relation names simultaneously, which allows a server to "offer" that URI to clients that support different link-relation names.这里的好处是,一个 URI 可以同时使用多个链接关系名称进行注释,这允许服务器“提供”该 URI 给支持不同链接关系名称的客户端。 In the case of forms the URI to send the request to is probably contained in the action attribute of the form element or the like.在 forms 的情况下,发送请求的 URI 可能包含在表单元素的操作属性等中

As you hopefully can see, with HATEOAS there is no need for a hard dependency on URIs, if so there may be a dependency on the link-relation name though.正如您希望看到的那样,使用 HATEOAS 不需要对 URI 的硬依赖,如果是这样的话,可能会依赖于链接关系名称。 It still requires URIs to learn where to send the request to, but through looking up the URI via its accompanying link relation name you make the handling of URIs much more dynamic as it allows a server to change the URI anytime it wants to or has to.它仍然需要 URI 来了解将请求发送到哪里,但是通过通过其随附的链接关系名称查找 URI,您可以使 URI 的处理更加动态,因为它允许服务器随时更改 URI。 .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM