本文介绍了HATEOAS 和链接/操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力思考如何(以及是否要)在我的 api 中实现 HATEOAS.我喜欢只为客户提供适合当前情况的行动的概念之一.但是我不确定我是否正确地实施了这个想法.

I'm trying to wrap my head around how to (and if to) implement HATEOAS in my api. I like one of the concept of feeding the client only actions that are appropriate in the current situation. However I'm not sure if I'm implementing this idea correctly.

假设我有一个资源类型order,其状态可以更改,它可以有不同的状态(processingaccepted拒绝过期、成功).然后我应该创建以下 json 对象:

Let's say I have a resource type order with a status that can be changed, it can have different statuses (processing, accepted, declined, expired, successful). Should I then create the following json object:

{
    ...
    "links": {
        "accept": "http://example.com/order/1/accept",
        "decline": "http://example.com/order/1/decline"
    }
}

还是我在这里创建了不必要的操作?如果以上是正确的,状态是否应该通过 PATCH 或 GET 更改?如果是 PATCH,人们怎么知道(违背了超媒体的目的)?

Or am I creating unnecessary actions here? And if above is correct, should the status be changed by a PATCH, or GET? And if it were PATCH, how would one know (defeating the purpose of hypermedia)?

忘记添加订单 ID

推荐答案

警告:除非您的域恰好是文档管理,否则如果您尝试将资源与域概念相匹配,您可能会陷入困境.Jim Webber 警告大约在几年前;在大多数情况下,您的资源是集成域的一部分.它们是用于与您的领域模型进行交互的小型数字纸张.

Warning: unless your domain happens to be document management, you may be getting yourself into a tangle if you try to match your resources with your domain concepts. Jim Webber warned about this years ago; in most cases, your resources are part of the integration domain. They are little digital pieces of paper that are used to interact with your domain model.

{
    ...
    "links": {
        "accept": "http://example.com/order/accept",
        "decline": "http://example.com/order/decline"
    }
}

这里的基本思想很好——如果客户端想要调用接受协议,他们知道使用哪个链接;对于拒绝协议也是如此.其他任何事情,客户都知道它不应该尝试做,因为链接不可用;例如,如果客户的目标是使订单过期,它就会知道它已经陷入了死胡同.

The basic idea here is fine - if the client wants to invoke the accept protocol, they know which link to use; likewise for the decline protocol. Anything else, the client knows it shouldn't be trying to do because the links are not available; for instance, if the goal of the client was to expire the order, it would know that it had run into a dead end.

这里URI的拼写有点奇怪;客户端不需要关心拼写,但请求应该是无状态的.如果订单是一种类型的资源,那么您如何传达接受/拒绝哪个订单.

The spelling of the URI here is a bit strange; the client shouldn't need to care about the spelling, but the request should be stateless. If order is a type of resource, then how are you communicating which order to accept/decline.

如果以上是正确的,状态应该通过 PATCH 还是 GET 来改变?

都不是.

GET 是错误的,因为广告资源支持 GET 是在声明操作是安全,这意味着中间组件可以推测性地跟随链接,预先加载结果以节省客户端时间.如果您理解传达客户

GET is wrong, because advertising that a resource supports GET is a claim that the operation is safe, which means that intermediary components can speculatively follow the link, pre-loading the result to save the client time. Not what you want to be doing if you are understanding the message to communicate a decision made by the client

PATCH 有两个问题.首先,它是为文档操作而设计的;如果您的应用程序是一个文档数据库,那么 PATCH 非常适合进行一个或多个范围的更改.但是对于处理业务模型的代理表示并不是那么好;客户端不是将其意图传达给服务器,而是传达其意图会对表示产生的副作用,然后服务器尝试从副作用中推断出意图.

PATCH has two issues. First, it's designed for document manipulation; if your application is a document database, then PATCH is fantastic for making one or several scoped changes. But it's not so great for dealing with proxy representations of the business model; instead of the client communicating its intent to the server, the client communicates the side effect that its intent would have on the representation, and then the server tries to deduce the intent from the side effect.

但你可能会绕过它;毕竟,您可以选择您支持的媒体类型,并且可能将自己限制在那些允许您表达客户意图的类型上.

But you could potentially get around that; after all, you can choose the media types your support, and could potentially limit yourself to those types which allow you to express the client's intent.

第二个问题是PATCH不是幂等的;它具有与 POST 相同的失败模式——如果服务器未确认请求,则客户端无法轻松确定重试请求是否安全.

The second issue is that PATCH is not idempotent; it has the same failure modes as a POST -- if the request isn't acknowledged by the server, the client's cannot readily determine if it is safe to retry the request.

直接的方法是将编辑视为类似于将手写笔记放入某人的收件箱

The straight forward approach is to think of the edits as analogous to putting a hand written note into somebody's inbox

应该接受订单 54321.请完成它.签字,客户.

换句话说,我们不是试图直接操纵订单资源,而是向收件箱发送一条笔记,这将产生操纵订单的副作用.客户端描述它想要的更改,服务器进行更改(或者不进行更改,如果您允许服务器拥有自主权).

In other words, we aren't trying to manipulate the order resource directly, but instead delivering a note to an inbox that will have the side effect of manipulating the order. The client describes the change it wants, the server makes the change (or not, if you are allowing the server to have autonomy).

对于这种方法,PUT(幂等)或 POST(非幂等)是合适的.实际上,您正在向收件箱集合中添加一条新消息,并且可以使用该习语来选择合适的方法.

For this approach, PUT (which is idempotent) or POST (which is not) are appropriate. In effect, you are adding a new message to the inbox collection, and can use that idiom to choose the suitable method.

如果是 PATCH,人们怎么知道(违背了超媒体的目的)?

客户端如何知道在links"属性中查找链接?

How would the client know to look for links in the "links" property?

浏览器如何知道如何处理 HTML 文档中的链接?

How does the browser know what to do with the links in an HTML document?

REST 的答案是:他们知道是因为您在设计媒体类型本身方面投入了大量精力.在 Web 的情况下,在设计 text/html 媒体类型上投入了大量时间和精力,因此任何以 html 设计的客户端都可以使用共享该理解的服务器生成的表示——客户端和服务器彼此分离,但共享一个共同点.

The REST answer is: they know because you've invested a bunch of effort in designing the media type itself. In the case of the web, a bunch of time and effort was invested in designing the text/html media type, and so any client that is designed with html in mind can consume the representation produced by a server that shares that understanding -- the client and server are decoupled from each other, but share a common ground.

在 HTML 的情况下,在大多数情况下,媒体类型定义了与链接关联的 HTTP 方法(表单除外,它允许表示从受限集合中指定方法).站在巨人的肩膀上.

In the case of HTML, for the most part the media type defines the HTTP methods associated with the links (the exception being forms, which allows the representation to specify a method from a restricted set). Stand on the shoulders of giants.

这篇关于HATEOAS 和链接/操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 09:22