如何从自描述 REST 发出对嵌套资源的初始请求 API

How to make initial request for nested resource from self describing REST API

背景:

我有一个从 REST API 中提取数据的单页应用程序。 API 的设计使得唯一需要的 URL 是 API 根,即 https://example.com/api 为其他资源提供 URL,这样客户端就不会不需要知道它们是如何构造的。

API 设计

API主要有3个类数据:

SPA 设计

使用 API 的应用程序具有用于列出模块、查看特定模块的详细信息和查看特定资源的视图。该应用程序的工作方式是将所有加载的数据保存在商店中。此存储一直持续到页面 closed/refreshed.

问题:

我的问题是,如果用户导航到资源的详细信息视图 (example.com/resources/1/) 然后他们刷新页面,我如何在不知道其 URL 的情况下加载该特定资源API?

可能的解决方案:

硬编码URLs

硬编码 URL 会相当简单,因为我同时控制 API 和客户端,但我真的更愿意坚持自我描述 API,其中客户端不需要知道 URLs.

递归获取

我可以递归地获取数据。例如,如果用户请求具有特定 ID 的 Resource,我可以执行以下步骤。

  1. 获取所有模块。
  2. 对于每个模块,获取其类别
  3. 查找包含所请求资源的类别并获取所请求资源的详细信息。

我担心的是我会提出很多不必要的要求。如果我们有 100 个模块,但用户只会查看其中的 1 个,我们仍然会发出 100 个请求来获取每个模块中的类别。

描述性URLs

如果我像 example.com/modules/123/categories/456/resources/789/ 一样嵌套 URL,那么我可以进行 3 次简单的查找,因为我可以避免搜索接收到的数据。这种方法的问题是 URL 很快就会变得笨拙,特别是如果我还想为每个资源包含一个 slug 时。但是,由于这种方法可以让我避免对 URL 进行硬编码并避免进行不必要的网络请求,因此它是目前我的首选。

备注:

如有任何解决此问题的想法,我们将不胜感激。

用户正在查看的当前 URL 以及到达当前位置所花费的步骤都是应用程序状态(在 HATEOAS 意义上)。

用户重载example.com/resources/1/只是简单的重新确认当前应用状态,客户端不需要做任何API遍历回到这里

您的客户端应用程序 应该 知道当前 URL,但是 URL 保存在客户端计算机上(在 RAM 或磁盘缓存中,或历史文件等)

API 的起点是(嗯,可以)编译到您的客户端。编译的 URLs 是将客户端连接到服务器的东西,而不是用户在使用客户端期间访问过的 URLs,包括当前的 URL.

你的问题"For example, if the user requests a Resource with a particular ID"说明你没有掌握HATEOAS提供的解耦

用户从不请求具有某某ID的资源。用户可以点击link得到一个查询表单,然后服务器提供一个生成请求到/collection/{id}的表单。 (在HTML中,这仅适用于查询字符串,而不适用于路径组件,但其他超媒体格式没有此限制)。
当用户在字段中提交带有 ID 号的表单时,客户端可以根据服务器+用户提供的数据构建请求URL。

在回答中扩展我的评论。

我认为这是一个非常普遍的问题,也是我自己一直在努力解决的问题。我认为 Nicholas Shanks 的回答并没有真正解决这个问题。

我特别针对这一部分提出了一些问题:

The user reloading example.com/resources/1/ is simply re-affirming the current application state, and the client does not need to do any API traversal to get back here.

Your client application should know the current URL, but that URL is saved on the client machine (in RAM, or disk cache, or a history file, etc.)

我由此得出的结论是,您应用程序上的 urls 仅在历史文件或磁盘缓存的生命周期内有效,不能与其他用户共享。

如果这对您的用例来说足够好,那么这可能是最简单的,但我觉得在很多情况下情况并非如此。最明显的一个确实是能够从前端应用程序共享 urls。

为了解决这个问题,我将问题总结为:

您需要能够无状态地将 url 从前端映射到 API

最简单但不正确的方法可能只是映射 API url 例如:

http://api.example.org/resources/1

直接url如:

http://frontend.example.org/resources/1

我遇到的问题是,这意味着 /resource/1 是从前端 url 获取的,只是添加到 api url。这不是我们应该做的事情,因为这意味着我们无法真正进化这个 api。例如,如果服务器决定 link 到不同的服务器,urls 中断。

另一种选择是生成 uris,例如:

http://frontend.example.org/http://api.example.org/resources/1
http://frontend.example.org/?uri=http://api.example.org/resources/1

我个人认为这并不太疯狂。 意味着前端需要能够加载该 uri 并找出 'view' 为后端 uri 加载什么。

第三种可能性是您添加另一个 api 可以:

None 这些想法对我来说听起来超级棒。我想要一个更好的解决方案来解决这个问题,但这些是我在考虑这个问题时想到的。

非常好奇是否有更好的想法!