【问题标题】:REST/HATEOAS - Available methods in HAL linksREST/HATEOAS - HAL 链接中的可用方法
【发布时间】:2017-12-10 05:08:41
【问题描述】:

我正在考虑使用 HATEOAS 定义一个 REST API。特别是,我发现为给定资源指示当前可用操作的概念非常有趣。

某些 HATEOAS 规范包含太多开销,无法满足我的需求,因此我查看了 HAL specification,因为我发现它非常简洁实用:

{
    _links: {
        self: { href: "/orders/523" },
        warehouse: { href: "/warehouse/56" },
        invoice: { href: "/invoices/873" }
    },
    currency: "USD",
    status: "shipped",
    total: 10.20
 }

但是,HAL 中的链接仅包含相关资源的列表,而不包含对它们的可用操作。按照上面的例子,我现在可以取消订单,还是不能取消?一些 HAL 示例通过使用特定 URL 进行取消来解决此问题,并且仅当可以取消时才在响应中添加相应链接:

"cancel": { "href": "/orders/523/cancel" }

但这不是很 RESTful。取消不是资源。取消是对资源的删除,即:

DELETE /orders/523

有没有一种用 HAL 表示这一点的好方法,还是我应该使用不同的 HATEOAS 规范?

我正在考虑返回一个与 self 具有相同 URL 的“取消”链接,但在这种情况下,客户必须知道要取消他们必须使用 DELETE 动词,这在 HATEOAS 响应中并未真正描述.

self: { "href": "/orders/523" },
cancel: { "href": "/orders/523" }

这会是 HATEOAS / HAL 推荐的方法吗?我知道 HAL 没有任何“方法”参数,我自己添加它会违反 HAL 规范。

【问题讨论】:

    标签: json rest api hateoas


    【解决方案1】:

    一些 HAL 示例通过使用特定 URL 进行取消来解决此问题,并且仅当可以取消时才在响应中添加相应的链接

    是的。就像网站一样:如果您想提醒客户端可能会到达某个其他应用程序状态,您需要向客户端提供一个链接,其中包括所涉及资源的标识符。

    但这不是很 RESTful。

    它可能不是“RESTful”,但肯定符合REST architectural style

    取消是对资源的删除,即:DELETE /orders/523

    您将域模型上的操作与集成模型上的操作混淆了。 REST API 所做的是通过协议引导客户端实现某种目的;它不是语义到HTTP的映射。

    吉姆·韦伯这样说:

    网络不是您的域;这是一个文档管理系统。所有 HTTP 动词都适用于文档管理域。 URI 不映射到域对象——这违反了封装。工作(例如:向域模型发出命令)是管理资源的副作用

    REST 约束之一是uniform interface;在 HTTP 的情况下,这意味着所有资源都以统一的方式理解方法; DELETE 表示RFC 7231, section 4.3.5中描述的语义。

    换句话说,如果我发送请求

    OPTIONS /x/y/z/foobar ...
    

    并且响应在Allow header 中包含DELETE,那我就知道是什么意思了。您的域中的副作用?我对副作用一无所知。

    在DELETE的定义中,注意以下几点

    相对较少的资源允许使用 DELETE 方法——它的主要用途是远程创作环境,用户对其效果有一定的指导。

    不管怎样,你问的不是DELETE,而是HAL

    有没有用 HAL 表示这个的好方法,还是我应该使用不同的 HATEOAS 规范?

    据我所知,官方的做法是用链接关系记录它。换句话说,不是使用“取消”作为链接关系,而是使用类似

    https://www.rfc-editor.org/rfc/rfc5023#section-5.4.2

    然后您的消费者,如果他们想发现链接的用途,可以按照关系了解正在发生的事情。

    HAL Discuss: Why No Methods? 有很多很好的信息。

    我喜欢 Mike Kelly 的总结:

    这个想法是可以通过链接传达可用的方法 关系文档,不需要在 json 消息中。

    【讨论】:

    【解决方案2】:

    根据来自 LosTechies 的 this article,从 CQRS 的角度来看,它接受使用诸如 /orders/<id>/<command> 之类的 URL 并使用 PUT 请求调用这些 URL。所以可以使用"cancel": { "href": "/orders/523/cancel" }

    但是,如果您绝对想使用DELETE,并且您只使用命令链接来修改您的资源(即/orders/<id>/<command>),就像文章提出的那样,您为什么不能只添加一个链接,例如"cancel": { "href": "/orders/523" }并扣除HTTP动词? 我的意思是根据 REST,只有 5 个主要动词(GET、POST、PUT、PATCH 和 DELETE)。我们不能在 /<ressource>/<id> 这样的 URL 上使用 POST,GET 已经定义为“自我”关系,我们上面提到修改(PUT)将由命令链接(即/<ressource>/<id>/<command>)处理,因为我们使用命令链接没有必要使用 PATCH。之后,剩下的唯一选择就是:DELETE。

    它并不完美,但它可以工作并且不会违反任何惯例。

    【讨论】:

    • ... according to REST there is only 5 main verbs ... REST 没有指定任何这些,它只是在论文本身中提到了一些操作,即 POST,即根本没有出现在 HTTP 的上下文中。由于 HTTP 方法是由 IANA 标准化和维护的,因此实际上您应该考虑支持 a couple more,至少它们是正确的 HTTP 方法,即使没有被广泛使用。
    • @RomanVottner 我说的是公认的 REST 约定和良好实践。 KevinDockx 在复数视觉上做了一个很棒的课程:app.pluralsight.com/library/courses/…
    • ... accepted REST conventions and best practices ... 是谁?典型的约定表明,像 cancel 这样的动词不应该放在 URI 中,因为当 Fielding 的论文一开始没有设置这样的约束时,动作应该由 HTTP 操作表示。实际上,URI 中的字符在使用 REST 交互模型的架构中并不重要,尽管很多人似乎认为这“不是 RESTful”。此类“惯例”应谨慎对待,因为它们描述了某些人的观点,但不一定是事实
    • @RomanVottner [...] by whom? Typical conventions state that verbs like cancel shouldn't be put in a URI as the action should be expressed by the HTTP operation [...]。 JimmyBogard 在这篇文章中这样做:lostechies.com/jimmybogard/2016/06/01/…
    猜你喜欢
    • 2018-05-08
    • 2019-03-23
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2016-12-11
    • 1970-01-01
    • 2016-05-23
    相关资源
    最近更新 更多