【问题标题】:RESTful client - how to process an external link?RESTful 客户端 - 如何处理外部链接?
【发布时间】: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/users url,带有rel 用户集合
  • 之后客户端显示一个带有标签的按钮:userlist
  • 我点击那个按钮,客户端从api获取数据,并打印用户列表
  • 如果我想和我的女朋友分享用户列表,那么我必须用 pushState 从客户端更改浏览器 url,例如从 http://my.client.comhttp://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 也许我们需要一种查询语言来查找资源?

标签: rest hateoas


【解决方案1】:

通常我们不想与任何人共享所有这些信息,因此我们不能仅将我们所在的当前页面导出所有这些信息。

将整个资源存储在客户端然后将其推送到服务器以更改服务器上的状态并没有错。如果您担心您的资源变得太大,尽管您可以将资源分开一点。假设您有一个订单资源,并且需要与一个地址相关联。您不需要将地址放在订单资源中,只需一个指向该地址的链接即可使用。用户可以独立添加或更改该地址。所以你可能有类似的东西

www.myapi.com/users/1234/shippingaddresses/default

客户端可以为这个资源添加一个新地址。然后在订单资源的正文中,您可以拥有该资源的链接

POST www.myapi.com/users/1234/orders
{
    ...order information...
    "shipping_address": "www.myapi.com/users/1234/shippingaddresses/default"
}

为了实现 RESTful,客户端不应构建该 URL,它应该在最近的某个时间点由服务器提供,可能是在用户选择要使用的地址时。例如,在上一步中,客户端可能已经请求了所有地址

GET www.myapi.com/users/1234/shippingaddresses

并在下拉列表中将地址列表呈现给用户。

【讨论】:

  • 我认为有误会。是的,允许在客户端存储和显示资源状态。我的意思是我们通常不想将所有这些信息存储在浏览器地址栏中。例如,通过在网上商店浏览目录,您希望在地址栏中显示当前产品 ID(用于复制粘贴,并将其作为链接分享给某人),但您不想拥有所有详细信息关于您当前购物车中的内容,或者您​​的会话 ID、个人信息等...所以我们通常只想分享有关 REST 客户端状态的部分信息...
  • 问题是 REST 客户端不应该有任何独立于服务器的状态。客户端从服务器拉下状态,对其进行修改,然后将其推回。您不应该在客户端之间独立于服务器共享复杂的状态。您应该在客户之间共享的最多可能是您正在查看的最后一个资源的书签。所有状态都应该通过服务器,如果您必须共享状态,您必须将其推送到服务器并让另一个客户端将其从服务器上拉下来。将状态从客户端复制到客户端视图之类的复杂 URI 是一个坏主意。
  • 你在很多事情上都是对的,所以我删除了我可能不好的答案(没有耐心阅读它)并接受你的。修复我的旧帖子是一项艰巨的工作......:S
猜你喜欢
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-27
  • 2015-08-13
  • 1970-01-01
相关资源
最近更新 更多