在阅读HATEOAS / Hypermedia约束时,我经常看到的一件事是资源应该具有某种类型的self / href。 对此的论点是客户端不需要知道如何来构造该特定资源的URL,例如:用于更新资源。
e.g。
{
//instead of "id":"123"
"href":"/api/v1/orders/123",
order state...
}
我喜欢这个主意。
但这个概念如何适合获取数据? 让我们说我需要获取具有特定订单ID的订单,客户将如何处理? 在这种情况下,我仍然需要知道如何构造资源的URL,对吗?
客户端应该如何知道查找资源的位置和方式? 它必须以某种方式了解API URL?
答案 0 :(得分:5)
您使用与在任何Web应用程序中使用的完全相同的概念来执行此操作:向客户端发送用于构建下一个请求的配方。在HTML中,您将使用HTML表单来执行此操作。如果您使用的是JSON,那么您的格式需要具有相同的概念,例如:使用URI模板,甚至是表单,即键值对列表,可能已经填写了一些值。
例如,之前的请求可能会返回如下内容:
{ "order": {
"link": {
"template": "https://your-api.com/orders/{id}",
"method": "GET",
"type": "application/json"
}
}
}
当然,您的代码仍然依赖于某些信息 - 在这种情况下,ID被称为" id"在模板中。但是通过添加这个间接,它不知道实际的URI。另请注意,我添加了方法和类型参数作为示例;是否选择使其可配置取决于您使用的格式。有关更详细的示例,请参阅(或使用)优秀的collection+json format。
答案 1 :(得分:5)
虽然可以提供URI Template,但在我必须这样做的时候,我总是认为有点气味。有时它是必要的,但如果我的API的主要部分最终使用该方法,我就不会将其称为HATEOAS或level 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"
}
]
}
]
}
我的客户可以在此列表中查找所需的订单,然后,一旦识别出有趣的订单,就可以按照具有"顺序"的相应链接。关系类型。
作为一般资源,RESTful Web Services Cookbook是回答这些问题不可或缺的。
答案 2 :(得分:4)
精心设计的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
}
我在这里定义了一个使用密钥作为操作名称的地图,或者使用HATEOAS术语中的 relation ,尽管我可以同样拥有一个名为{{1的密钥的地图列表分别为"rel"
和"cancel"
的值和值。
另一个角色,比如航运协调员,可能看不到"list_orders"
操作,因为他们没有取消订单的权限。
答案 3 :(得分:1)
让我们来看看你的情况。我会这样看待它。您的搜索始终返回交互(即URL)。然后,客户端始终可以从那里开始导航以获取数据。
关键是不返回值,只返回表示。
我们正在使用这个实现的平台。它有一种独特的基于交互的语言。该平台完全符合HATEOAS标准,在向其发送搜索时返回URL。
在您的示例中,如果我们发送预订ID。它返回具有此预订ID的所有订单网址。然后客户端可以通过这些URL进行导航。
我希望这有助于您的查询。