【发布时间】:2013-11-18 22:36:17
【问题描述】:
通过 RESTful 最佳服务,有 HATEOAS 原则告诉我们,我们不应该允许客户端构建资源 URL-s。如果我们遵循这个原则,就很难共享客户端的当前状态。例如,如果您在服务器上有一个 REST 服务,并且您通过 AJAX 使用单页 javascript 客户端获取数据,那么您将有 2 个 url。一个用于客户端状态,一个用于您从 REST 服务获得的结果。由于 pushState,您只能与使用共享客户端状态...如果有人使用以前共享的 url 运行客户端,那么她的客户端将不知道它应该调用的 REST 服务的 url,因为客户端无法构建URL-s,只需从 REST 服务接收并使用它。
例如:
- 我浏览
http://my.client.com - 页面从
http://my.api.com获取根资源,并返回一个链接 - 链接包含
http://my.api.com/usersurl,带有rel 用户集合 - 之后客户端显示一个带有标签的按钮:userlist
- 我点击那个按钮,客户端从api获取数据,并打印用户列表
- 如果我想和我的女朋友分享用户列表,那么我必须用 pushState 从客户端更改浏览器 url,例如从
http://my.client.com到http://my.client.com/users - 之后我将该网址发送给我的女朋友
- 她将其复制粘贴到浏览器地址栏中,然后按 Enter。在那之后,客户说了一个巨大的 wtf,因为 - 就像 John Snow - 它不知道那个 url 意味着什么状态......
这个问题可以解决,如果我们允许客户端从 url:http://my.client.com/users 构建GET http://my.api.com/users,但这不会是 RESTful,因为客户端不应该构建 api url...
如果我想在客户端显示一个嵌套菜单,那就是另一个问题,因为我不想在每个答案中都发送整个菜单树。我可以为每个资源创建一个菜单投影,或者使用 OPTIONS 方法或自定义方法来发送该数据,但这会很麻烦。这可以通过关注rel=up 链接来解决 - 从 REST 服务获得 - 串联,但如果我不知道应该从哪里关注,它将无法工作......
google bots 也会出现这个问题...
我怎样才能既解决这个问题又保持在 HATEOAS 原则的范围内?
【问题讨论】:
-
“my.client.com”的目的是什么。您不能将您的网络浏览器指向“my.api.com”吗?您似乎正在构建两个客户端,浏览器和在某个地方运行的客户端服务。您正在链接客户端。这似乎是在重新发明轮子。 Web 浏览器已经是 HTTP 客户端。
-
REST 服务应该是无状态的,所以我必须使用客户端来存储状态...通过常规 Web 应用程序您是对的,但这是一个 RESTful Web 服务...
-
所以 my.client.com/users 实际上是对单页 Web 应用程序上的 JavaScript 的命令,而不是对外部服务的调用。在这种情况下,客户端 JavaScript 应该基于该命令重建其对服务器的了解。它应该说用户想要用户,所以我将从根 my.api.com 开始,找到指向用户的链接,可能是 /users 或其他东西,对该资源执行 GET 并将其显示给用户。用于向浏览器中运行的 JavaScript 发出命令的 URI 应该与服务器上的 URI 无关。
-
将该 URI(这不是真正的 URI)提供给您的女朋友并不重要,因为当她输入它时,JavaScript 应用程序将从根目录重新发现服务器的资源。 URI 应该只对客户端有意义。
-
好的,但是如何重新发现以及如何识别它正在寻找的资源是
service/users?例如,如果资源是深度嵌套的,则可能需要对服务进行大量 http 调用才能找到它……所以理论上应该这样做,但实际上我不知道该怎么做…… . :S 也许我们需要一种查询语言来查找资源?