关于rest:如何避免在具有深度链接的 RESTful 客户端/服务器 Web 应用程序中对 URL 进行硬编码?

How can I avoid hardcoding URLs in a RESTful client/server web app with deep linking?

我正在开发一个 SPA,它是 RESTful Web 服务的客户端。客户端和服务器都是同一个项目的一部分,即我可以自由修改双方的代码。我一直在阅读 RESTful API 设计,以尝试确保我以"正确"的方式做所有事情。我从阅读中得到的一个收获是,RESTful 服务应该发布超链接,以便客户端可以访问更多信息,并且客户端除了入口点之外不应该有关于服务 URL 的硬编码信息。使用超链接可以让客户端在服务器更改 URL 时更加灵活。

但是,当允许用户链接到特定客户端状态时,我无法弄清楚该架构应该如何工作。例如:

其中一个视图是可供购买的图书列表。客户端将浏览器的位置设置为 /books/ 以标识此页面,后端数据来自端点 /api/books/,从发布该 URL 的 API 入口点检索。服务 URL 响应如下 JSON 文档:

1
2
3
4
5
6
7
8
[
    {"title":"The Great Gatsby",
    "id": 24,
    "url":"http://localhost/api/books/24/"},

    < and so on >

]

客户端使用它来生成可读的链接,当点击这些链接时,会转到单本书的详细视图。浏览器的位置已更新为 /books/the-great-gatsby/24/,因此用户可以将此视图添加为书签并链接到它。

当用户直接点击该链接时,客户端如何处理?如果没有硬编码的 URL,它如何知道从哪里获取本书的信息?

我能想到的最好的方法是以下请求序列:

  • GET /api/ - 查看可用的服务(以查找是否有书籍)
  • OPTIONS /api/books/ - 查看书籍上可用操作的描述(例如,它可以确保它可以通过 ID 找到书籍)
  • GET /api/books/?id=24 - 查看它是否可以找到 ID 与浏览器位置中的 ID 匹配的书籍。
  • GET /api/books/24/ - 实际检索数据
  • 任何较短的内容都意味着客户端对 API 的 URL 具有硬编码知识。但是,从 Web 应用程序的angular来看,这似乎非常低效。

    我错过了什么技巧吗?有没有办法让客户端"知道"如何在不以某种方式硬编码 /api/books/24/ 端点的情况下获取有关图书 ID 24 的更多详细信息?


    如果您从服务器请求此资源 /books/the-great-gatsby/24/,服务器应该以特定于该 URL 的内容进行响应。目前,您可能正在分析 window.location 这有点 hack。

    如果 /books/the-great-gatsby/24/ 是静态内容,那么您几乎没有选择:您将客户端的当前状态显式存储在某处(即 /books?data=api/books/24 或隐式 /books/the-great-gatsby/24/ 这导致客户端必须知道如何将其转换为 API 资源。

    RESTful 方式是使用超文本来指示任何相关资源(即要呈现的数据)在哪里,这使得标签成为一个合适的选择。

    即抛弃静态内容,用 <head><link href="api/books/24" ....></link></head>

    渲染 /books/the-great-gatsby/24/

    但是,如果您始终保留对客户端的控制权并且不打算将 API 发布给第三方,那么放弃 RESTful 并转而使用 RESTish 可能会更有效率。


    另一个想法:

    您已经做出了以下假设,具有路径组件 /books/the-great-gatsby/24/ 的 url 应该以某种方式映射到具有类似 /api/books/24/ 的路径的 url。

    为什么不添加一个小型服务服务器端来为您进行此映射?例如:

    1
    /lookup?url=/books/the-great-gatsby/24/

    如果您担心额外的请求,该端点可以只返回实际响应。它仍然可以有一个引用真实 url 的 self 链接(或规范,如果您愿意)。

    或者它可以只是重定向,并使用 HTTP/2 立即推送真实资源。