使用HATEOAS时找到一个宁静的资源?

Rog*_*son 4 rest hateoas hypermedia

在阅读有关HATEOAS /超媒体约束的内容时,我经常看到的一件事是资源应该具有某种类型的self/href.对此的论点是客户端不应该知道如何构造该特定资源的URL,例如用于更新资源.

例如

{
     //instead of "id":"123"
     "href":"/api/v1/orders/123",

     order state...
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这个主意.

但是这个概念如何适合获取数据?假设我需要获取具有特定订单ID的订单,客户将如何处理该订单?在这种情况下,我仍然需要知道如何构造资源的URL,对吧?

客户端应该如何知道查找资源的位置和方式?它必须以某种方式了解API URL?

Ste*_*kov 5

您可以使用与在任何Web应用程序中使用的完全相同的概念来执行此操作:向客户端发送用于构建下一个请求的配方.在HTML中,您将使用HTML表单来执行此操作.如果您正在使用JSON,那么您的格式需要具有相同的概念,例如使用URI模板,甚至是表单,即键值对列表,可能已经填充了一些值.

例如,先前的请求可能返回如下内容:

{ "order": {
    "link": {
        "template": "https://your-api.com/orders/{id}",
        "method": "GET",
        "type": "application/json"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,您的代码仍然依赖于某些信息 - 在这种情况下,ID在模板中称为"id".但是通过添加这个间接,它不知道实际的URI.另请注意,我添加了方法和类型参数作为示例; 是否选择使其可配置取决于您使用的格式.有关更详细的示例,请参阅(或使用)优秀的集合+ json格式.


Mar*_*ann 5

虽然你可以提供一个URI模板,但是当我不得不这样做时,我总是觉得有点气味.有时这是必要的,但如果我的API的主要部分最终使用该方法,我不会将其称为HATEOAS或3级 RESTful API.

如何对场景建模很大程度上取决于上下文,这可能就是Pete询问用例的原因.

通常,您可以使用与为人类可用的网站建模相同的方式建模RESTful API.例如,您可以拥有一个列出所有用户订单的资源,例如首先按最新订单排序:

{
    "orders": [
        {
            "date": "2015-01-25",
            "total": 1234,
            "links": [
                {
                    "rel": "order",
                    "href": "https://follow.the.link"
                }
            ]
        },
        {
            "date": "2015-01-22",
            "total": 1337,
            "links": [
                {
                    "rel": "order",
                    "href": "https://follow.this.other.link"
                }
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我的客户端可以在此列表中查找所需的顺序,然后,一旦识别出有趣的顺序,就可以跟随具有"顺序"关系类型的相应链接.

作为一般资源,RESTful Web Services Cookbook是回答这些问题所不可或缺的.

  • 正是我脑子里的答案.从遗留系统过渡到REST API的需求似乎需要牺牲URI模板. (3认同)

Dan*_*rth 5

精心设计的HATEOAS API将具有清晰的入口点,其余的应用程序行为可从此处发现。

由于问题是关于HATEOAS的,所以我想说使用URI模板会使客户承担太多责任。相反,您应该为给定当前应用程序状态的资源上的每个有效操作提供一个显式URL。

这不仅仅是一个风格问题。如果服务器提供了模板,则客户端开发人员必须编写代码以填充模板,这将在模板之间创建耦合。您现在必须更改服务器端URL结构,而不破坏与客户端的合同。使用HATEOAS,您可以将URL与资源上允许的每个操作相关联,而客户端只关心该操作。URL实际上是一个不透明的句柄:就像Ian Robinson所说的:“选择自己的冒险”

HATEOAS与使用超媒体(包含指向其他媒体的链接的媒体)有关,以使客户端能够在应用程序周围进行导航,而无需了解其最后收到的响应。这意味着每个响应都应为客户端提供代表当前资源上所有有效操作的即用型URL。

请记住,通过有线方式获得的东西只是资源的一种表示形式(REST代表REpresentational State Transfer)。根据您当前的上下文,例如您的当前权限集和当前应用程序状态,同一资源可以有不同的表示形式。不同的表示形式可以合理地提供不同的后续操作。

使用您的示例,订单的所有者可能会看到以下内容:

{
  "id": "/api/v1/orders/123", // reference to the current resource
  "rel": {
    "cancel": {
      "url": "/api/v1/orders/cancel?order_id=123",
      "method": "POST",
      // Metadata about what the cancel operation returns...
    },
    "list_orders": {
      "url": "/api/v1/orders",
      "method": "GET",
      // Metadata about what the list_orders operation returns...
    },
    // ...
    // Other operations available to the owner
  },
  // ...
  // Order state
}
Run Code Online (Sandbox Code Playgroud)

在这里,我定义了一个映射,该映射使用键作为操作名称或HATEOAS术语中的关系,尽管我同样可以拥有一个映射表列表,其键名为"rel",值分别为"cancel""list_orders"

运输协调员说,另一个角色可能看不到该cancel操作,因为他们没有取消订单的权限。