在使用HATEOAS时查找restful资源?

在使用HATEOAS时查找restful资源?,rest,hateoas,hypermedia,Rest,Hateoas,Hypermedia,当阅读HATEOAS/Hypermedia约束时,我经常看到的一件事是资源应该有某种self/href。 这样做的理由是,客户机不需要知道如何为特定资源构造URL,例如更新资源 e、 g 我喜欢这个主意 但是,这个概念如何与获取数据相适应呢? 假设我需要获取具有特定订单id的订单,客户将如何处理? 在这种情况下,我仍然需要知道如何构造资源的URL,对吗 客户机应该如何知道在哪里以及如何查找资源? 它必须以某种方式了解API URL?您使用与任何web应用程序中使用的概念完全相同的概念来完成此操作

当阅读HATEOAS/Hypermedia约束时,我经常看到的一件事是资源应该有某种self/href。 这样做的理由是,客户机不需要知道如何为特定资源构造URL,例如更新资源

e、 g

我喜欢这个主意

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

客户机应该如何知道在哪里以及如何查找资源?
它必须以某种方式了解API URL?

您使用与任何web应用程序中使用的概念完全相同的概念来完成此操作:向客户端发送生成下一个请求的方法。在HTML中,您可以使用HTML表单来实现这一点。如果您使用的是JSON,那么您的格式需要具有相同的概念,例如使用URI模板,甚至是表单,即键值对列表,可能已经填充了一些值

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

{ "order": {
    "link": {
        "template": "https://your-api.com/orders/{id}",
        "method": "GET",
        "type": "application/json"
    }
  }
}
当然,您的代码仍然依赖于一些信息——在本例中,id在模板中被称为“id”。但是通过添加这个间接寻址,它不知道实际的URI。还请注意,我添加了方法和类型参数作为示例;您是否选择使其可配置取决于您使用的格式。对于一个更详细的例子,请参阅(或使用)优秀。

虽然你可以提供一个,但我总是认为当我必须做的时候,有一点“强烈”的气味< /强>。有时这是必要的,但如果我的API的一个主要部分最终使用了这种方法,我不会将其称为HATEOAS或RESTful API

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

通常,您可以像对人类可用的web站点建模一样,对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"
                }
            ]
        }
    ]
}
我的客户可以在这个列表中查找它需要的订单,然后,一旦确定了感兴趣的订单,就可以遵循具有“订单”关系类型的相应链接


作为一个通用资源,是回答这类问题必不可少的工具。

一个设计良好的HATEOAS API将有明确的入口点,从那里可以发现应用程序的其他行为

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

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

HATEOAS是关于使用包含指向其他媒体的链接的超媒体媒体,使客户机能够在应用程序周围导航,而不必知道它收到的最后一个响应。这意味着每个响应都应该向客户端提供表示当前资源上所有有效操作的现成URL

请记住,通过连接得到的只是资源的表示(REST代表表示性状态传输)。根据您当前的上下文(例如您当前的权限集)和当前的应用程序状态,同一资源可以有不同的表示形式。不同的表示可以合法地提供不同的后续操作

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

{
  "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
}
在这里,我定义了一个使用键作为操作名称的映射,或者用HATEOAS术语中的关系,尽管我同样可以有一个映射列表,其中键名为
“rel”
,值分别为
“cancel”
“list\u orders”


另一个角色,比如发货协调员,可能看不到取消操作,因为他们没有取消订单的权限。

让我们看看您的情况。他们是我看待它的方式。您的搜索总是返回一个交互(即URL)。然后,客户机可以始终从那里开始导航以获取数据

关键是不要返回值,而只返回表示形式

我们正在使用一个平台来实现这一点。它有一种独特的基于交互的语言。该平台完全兼容HATEOAS,在向其发送搜索时返回URL

在您的示例中,如果我们发送一个预订id,它将返回具有该预订id的所有订单url。然后,客户端可以浏览这些URL


我希望这有助于你的提问

假设我们有一个编辑表单,那么工作流将类似于:->请求根/api->示例响应->构建URL->请求顺序。正确理解了吗?需要从哪里获取id?实际使用情况是什么?服务器端应用程序根据orderid显示指向客户端应用程序的链接,以编辑特定订单。用户单击链接,客户端应用程序打开upp并需要获取订单。。必须是非常常见的场景(?)客户端应用程序是动态的吗?这意味着,您不是在重新加载页面,而是在使用XHR进行状态转换?是的,SPA类型的应用程序,但从服务器应用程序UI打开,服务器不知道rest api。在这种情况下,它从DB获取订单ID。。(传统应用程序正在迁移到SPA)然后Stefan的答案是li
{
  "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
}