在HATEOAS体系结构中,您指定HTTP谓词?

Sle*_*led 25 rest hateoas

我正在阅读有关HATEOAS文章,虽然我理解为响应中的进一步操作提供URL的想法,但我没有看到您在何处指定应使用哪些HTTP谓词与这些URL进行交互.

例如,什么是HATEOAS,为什么它对我的REST API很重要?,如何从这个回应

GET /account/12345 HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
    <account_number>12345</account_number>
    <balance currency="usd">100.00</balance>
    <link rel="deposit" href="/account/12345/deposit" />
    <link rel="withdraw" href="/account/12345/withdraw" />
    <link rel="transfer" href="/account/12345/transfer" />
    <link rel="close" href="/account/12345/close" />
</account
Run Code Online (Sandbox Code Playgroud)

你知不知道我是否应该发出HTTP PUTPOST/account/12345/close

Cor*_*all 32

不要在你的URI中加入动词(例如/ account/12345/transfer).URI表示资源,而不是动作.

动词使用HTTP协议(例如被定义GET,POST,PUT,OPTIONS,DELETE等等).REST是一种具有一组约束的体系结构设计,HTTP是一种遵循这些约束的协议.HTTP定义了一组有限的动词,用于将资源的状态从客户端传输到服务器,反之亦然.根据定义,您仅限于这些动词.

客户端应根据尝试的内容决定使用哪个HTTP谓词.服务器不需要告诉它有什么动词,它已经基于HTTP协议知道了.

如果客户端需要知道它可以在资源上使用哪些动词,它可以使用OPTIONS动词查询资源并查看Allow响应中的标题(假设服务器返回此信息,如果它有用,则应该返回该信息).有些资源可能只接受GET,而其他资源可能会接受其他资源,如POST和PUT.

查看HTTP规范,了解在什么上下文中使用什么动词.

举一个你原来的帖子的例子.假设您有一个URI为的帐户资源

/accounts/12345
Run Code Online (Sandbox Code Playgroud)

并且您想要关闭该帐户.记住REST是状态转移.客户端正在关闭帐户,因此帐户处于关闭状态.然后它将该状态传输到服务器,以便客户端和服务器彼此一致.因此PUT,客户端状态(处于关闭状态的资源)进入服务器

PUT /accounts/12345
Run Code Online (Sandbox Code Playgroud)

请求的主体应包含处于关闭状态的资源的表示.假设您使用XML来表示帐户资源,它将是这样的

PUT /accounts/12345

<?xml version="1.0"?>
<account>
    <account_number>12345</account_number>
    <balance currency="usd">100.00</balance>
    <state>closed</state>
</account>
Run Code Online (Sandbox Code Playgroud)

服务器上的资源现在镜像客户端上的资源.两者都处于封闭状态.如果您不想在每次更改其中一个属性时传输整个资源,则可以将它们拆分为资源层次结构.将帐户的状态设置为自己的资源,并将其设置为PUT以进行更改

PUT /accounts/12345/status

<?xml version="1.0"?>
<state>closed</state>
Run Code Online (Sandbox Code Playgroud)

  • 有一篇很好的文章[这里](https://opencredo.com/designing-rest-api-fine-grained-resources-hateoas-hal/),为什么你会接受建模为资源的行动 (2认同)

Cel*_*oet 10

你的问题在Stackoverlow上有很多答案,但是大部分都是你要问的原因,我怀疑你总觉得它们部分不满意.

如果我们接受Roy Fielding的话,就不可能使用HTTP/HTML将大多数商业交互式客户端应用程序编写为SOA RESTful/HATEOAS.我不能说,在其他媒体中也许有可能.

因此,实际的答案是" 在文档中查找 "和" 使用该应用程序知识编写您的客户 ",并帮助" 忽略我们通过这样做违反Fielding规则的事实 ".

我倾向于设计提供此方法的JSON响应:

GET /account/12345 HTTP/1.1
{
    "account": {
        "number": "12345",
        "currency": "usd",
        "balance": "100.00",
        "deposit": {
            "href": "/account/12345/deposit",
            "action": "POST"
        },
        "withdraw": {
            "href": "/account/12345/withdraw",
            "action": "POST"
        },
        "transfer": {
            "href": "/account/12345/transfer",
            "action": "POST"
        },
        "close": {
            "href": "/account/12345/close",
            "action": "DELETE"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

...根据需要为设计添加其他属性,但这些是基础知识.

我相信这允许以RESTful方式编写消费客户端,但这样做我正在使用响应主体,Fielding说这不是他想要的.

我会提供这个解释分开给答案:


菲尔丁说:"我对使用任何基于HTTP的接口调用REST API的人数感到沮丧." (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven).

请注意他如何如此大力地说" 任何 "基于HTTP的界面.

他的"讲座"中最相关的部分是这样的:

" 应该输入REST API,除了初始URI(书签)之外没有任何先验知识,并且适用于目标受众的标准化媒体类型集合(即,任何可能使用API​​的客户都应该理解).如图所示,所有应用程序状态转换必须由客户端选择服务器提供的选择来驱动,这些选择存在于接收的表示中或者由用户对这些表示的操纵所暗示.转换可以由客户端的媒体知识确定(或限制)类型和资源通信机制,两者都可以在运行中进行改进(例如,按需代码).[这里的失败意味着带外信息驱动交互而不是超文本.] "

他说这是因为HTTP/HTML应用程序URI 媒体类型只是"text/html",其中的动词在哪里?没有一个.URI无法告诉您Verb需要使用/导航的内容,因此您不能仅使用带内数据来在您的客户端中动态构建"下一个"导航.

他解释说,他认为我们将URI作为CDATA的一部分,包括"方法",或者URI的上下文无疑会提供它,就像FORM元素那样.他明确指责OpenSocialst REST API声明它不是RESTful.

这里:" 具有href属性的锚元素创建一个超文本链接,当选择该链接时,在对应于CDATA编码的href属性的URI上调用检索请求(GET)."标识符,方法和媒体类型是正交关注点 - 方法没有给出媒体类型的含义.相反,媒体类型告诉客户端使用什么方法(例如,锚意味着GET)或如何确定要使用的方法(例如,表单元素表示查看方法属性).客户端应该已经知道方法的含义(它们是通用的)以及如何取消引用URI.

请注意,他说客户应该已经知道方法的含义,他并没有说客户应该已经知道它们什么- 这就是你提出问题的原因.很多人都在努力解决这个问题,因为在大多数SOA环境中我们实际上并没有像这样构建我们的应用程序.

像很多工程师一样,我只是希望菲尔丁能够做出澄清或重新陈述,但他不仅没有这样做,而且还作为工程师向我们发出了两个进一步的警告,他的声明加倍,说我们应该停止调用我们的API的RESTful并接受我们正在构建RPC.

我认为类似JSON元素的方法是一个可靠的桥梁,但我没有回答我们使用请求主体这样做的事实,而不依赖于媒体类型来暗示它.

最后,在HTTP中有一个名为OPTIONS的新动词,对于给定的URI,它将返回允许的动词动作列表.我认为Fielding有一手编写这个HTTP版本.这将允许客户端在没有禁止的内部应用程序知识的情况下一般地构造URI导航.但这有三个我在实际世界中可以想到的问题:

  1. 您必须将一种机制编码到您的服务聚合中,以便为您尝试返回的每个URI进行调用,并且由于许多数据包含许多URI(HAL中的_links),这会在您的服务响应构造中添加许多额外的"跳跃".我们可能都会抱怨这一点.
  2. 事实上,没有声称是RESTful的SOA站点实际上实现了OPTIONS动词方法调用,无论如何都要进行此查询.
  3. 我们都会抱怨它为客户的处理添加的"不必要的"额外呼叫(特别是在电子商务领域)以及它使我们超越SLA要求的倾向.


Wil*_*ung 7

你知道你应该PUT或POST到/ account/12345 /关闭吗?

您可以参考API的文档,这就是您所知道的.HATEOS不是正式文档的替代品.REST API需要文档,就像任何其他API一样.

HATEOS可让您了解特定资源的其他选项.它没有告诉您为什么要使用这些选项,或者您将发送哪些信息.内容类型仅表达语法和高级语义,而不表示应用程序级语义,因此它们也不是文档.

如果您想知道如何使用REST API,请阅读文档.如果您希望其他人使用您的REST API,请向他们提供文档.

这里没有魔力.