一个设计良好的 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 术语中的关系,尽管我同样可以拥有一个映射列表,其中的键分别称为and和"rel"
值。"cancel"
"list_orders"
另一个角色,比如运输协调员,可能看不到cancel
操作,因为他们无权取消订单。