HATEOAS 和 links/actions
HATEOAS and links/actions
我正在思考如何(以及是否)在我的 api 中实施 HATEOAS。我喜欢其中一种概念,即只为客户提供适合当前情况的操作。但是我不确定我是否正确地实现了这个想法。
假设我有一个资源类型 order,其状态可以更改,它可以有不同的状态(processing,已接受、已拒绝、已过期、成功)。我是否应该创建以下 json 对象:
{
...
"links": {
"accept": "http://example.com/order/1/accept",
"decline": "http://example.com/order/1/decline"
}
}
还是我在这里创建了不必要的操作?如果以上是正确的,状态是否应该通过 PATCH 或 GET 更改?如果是 PATCH,怎么会知道(违背超媒体的目的)?
编辑:忘记添加订单号
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).
警告:除非您的领域恰好是文档管理,否则如果您尝试将您的资源与您的领域概念相匹配,您可能会陷入困境。吉姆·韦伯 warned about this years ago;在大多数情况下,您的资源是集成域的一部分。它们是用于与您的域模型交互的小数字纸片。
{
...
"links": {
"accept": "http://example.com/order/accept",
"decline": "http://example.com/order/decline"
}
}
这里的基本思想很好——如果客户端想要调用接受协议,他们知道使用哪个 link;拒绝协议也是如此。任何其他事情,客户知道它不应该尝试做,因为 link 不可用;例如,如果客户端的目标是使订单过期,它会知道它 运行 进入了死胡同。
这里URI的拼写有点奇怪;客户端不需要关心拼写,但请求应该是无状态的。如果订单是 类型 的资源,那么您如何将哪个订单传达给 accept/decline。
And if above is correct, should the status be changed by a PATCH, or GET?
都没有。
GET 是错误的,因为宣传资源支持 GET 是在声明该操作是 安全的,这意味着中间组件可以推测性地遵循link,预加载结果以节省客户端时间。如果您理解传达 客户
做出的决定的消息,则不是您想要做的
PATCH 有两个问题。首先,它是为文档操作而设计的;如果您的应用程序是一个文档数据库,那么 PATCH 非常适合进行一个或多个范围内的更改。但它对于处理业务模型的代理表示并不是很好;客户端不是将其意图传达给服务器,而是传达其意图对表示的副作用,然后服务器尝试从副作用中推断出意图。
但你有可能绕过这个问题;毕竟,您可以选择您支持的媒体类型,并可能将自己限制在那些允许您表达客户意图的类型。
第二个问题是PATCH不是幂等的;它具有与 POST 相同的故障模式——如果服务器未确认请求,则客户端无法轻易确定重试请求是否安全。
直接的方法是将编辑视为类似于将手写便条放入某人的收件箱
Order 54321 should be accepted. Please get it done.
Signed, the client.
换句话说,我们并不是要直接操纵订单资源,而是将便条发送到收件箱,这会产生操纵订单的副作用。客户端描述它想要的更改,服务器进行更改(或者不进行更改,如果您允许服务器具有自治权)。
对于这种方法,PUT(幂等)或 POST(不是)是合适的。实际上,您是在向收件箱集合中添加一条新消息,并且可以使用该惯用语来选择合适的方法。
And if it were PATCH, how would one know (defeating the purpose of hypermedia)?
客户端如何知道在 "links" 属性 中查找 link?
浏览器如何知道如何处理 HTML 文档中的 link?
REST 答案是:他们知道,因为您在设计媒体类型本身方面投入了大量精力。就网络而言,在设计 text/html 媒体类型上投入了大量时间和精力,因此任何设计时考虑到 html 的客户端都可以使用由服务器生成的表示分享这种理解——客户端和服务器彼此分离,但有一个共同点。
在 HTML 的情况下,媒体类型大部分定义了与 link 相关联的 HTTP 方法(表单除外,它允许表示指定来自一个限制集)。站在巨人的肩膀上
我正在思考如何(以及是否)在我的 api 中实施 HATEOAS。我喜欢其中一种概念,即只为客户提供适合当前情况的操作。但是我不确定我是否正确地实现了这个想法。
假设我有一个资源类型 order,其状态可以更改,它可以有不同的状态(processing,已接受、已拒绝、已过期、成功)。我是否应该创建以下 json 对象:
{
...
"links": {
"accept": "http://example.com/order/1/accept",
"decline": "http://example.com/order/1/decline"
}
}
还是我在这里创建了不必要的操作?如果以上是正确的,状态是否应该通过 PATCH 或 GET 更改?如果是 PATCH,怎么会知道(违背超媒体的目的)?
编辑:忘记添加订单号
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).
警告:除非您的领域恰好是文档管理,否则如果您尝试将您的资源与您的领域概念相匹配,您可能会陷入困境。吉姆·韦伯 warned about this years ago;在大多数情况下,您的资源是集成域的一部分。它们是用于与您的域模型交互的小数字纸片。
{
...
"links": {
"accept": "http://example.com/order/accept",
"decline": "http://example.com/order/decline"
}
}
这里的基本思想很好——如果客户端想要调用接受协议,他们知道使用哪个 link;拒绝协议也是如此。任何其他事情,客户知道它不应该尝试做,因为 link 不可用;例如,如果客户端的目标是使订单过期,它会知道它 运行 进入了死胡同。
这里URI的拼写有点奇怪;客户端不需要关心拼写,但请求应该是无状态的。如果订单是 类型 的资源,那么您如何将哪个订单传达给 accept/decline。
And if above is correct, should the status be changed by a PATCH, or GET?
都没有。
GET 是错误的,因为宣传资源支持 GET 是在声明该操作是 安全的,这意味着中间组件可以推测性地遵循link,预加载结果以节省客户端时间。如果您理解传达 客户
做出的决定的消息,则不是您想要做的PATCH 有两个问题。首先,它是为文档操作而设计的;如果您的应用程序是一个文档数据库,那么 PATCH 非常适合进行一个或多个范围内的更改。但它对于处理业务模型的代理表示并不是很好;客户端不是将其意图传达给服务器,而是传达其意图对表示的副作用,然后服务器尝试从副作用中推断出意图。
但你有可能绕过这个问题;毕竟,您可以选择您支持的媒体类型,并可能将自己限制在那些允许您表达客户意图的类型。
第二个问题是PATCH不是幂等的;它具有与 POST 相同的故障模式——如果服务器未确认请求,则客户端无法轻易确定重试请求是否安全。
直接的方法是将编辑视为类似于将手写便条放入某人的收件箱
Order 54321 should be accepted. Please get it done. Signed, the client.
换句话说,我们并不是要直接操纵订单资源,而是将便条发送到收件箱,这会产生操纵订单的副作用。客户端描述它想要的更改,服务器进行更改(或者不进行更改,如果您允许服务器具有自治权)。
对于这种方法,PUT(幂等)或 POST(不是)是合适的。实际上,您是在向收件箱集合中添加一条新消息,并且可以使用该惯用语来选择合适的方法。
And if it were PATCH, how would one know (defeating the purpose of hypermedia)?
客户端如何知道在 "links" 属性 中查找 link?
浏览器如何知道如何处理 HTML 文档中的 link?
REST 答案是:他们知道,因为您在设计媒体类型本身方面投入了大量精力。就网络而言,在设计 text/html 媒体类型上投入了大量时间和精力,因此任何设计时考虑到 html 的客户端都可以使用由服务器生成的表示分享这种理解——客户端和服务器彼此分离,但有一个共同点。
在 HTML 的情况下,媒体类型大部分定义了与 link 相关联的 HTTP 方法(表单除外,它允许表示指定来自一个限制集)。站在巨人的肩膀上