api - 避免在前端构建 (REST API) URL
问题描述
我已经在后端工作了一段时间,最近才开始在前端工作,这让我更接近端到端的 REST 实现。
更重要的是,REST 的一个重要原则是使其可发现和一致,以便客户端知道如何通用地处理资源(HATEOAS、JsonApi 等)。我一直在阅读这篇 Google 文章,其中有以下几点:
如果一个 API 简单直接地使用 HTTP,它只需要记录三四件事。(如果一个 API 需要您阅读大量文档来学习如何使用它,那么它可能没有使用 HTTP 作为统一 API。) HTTP API 的四个元素是:
- 数量有限的固定、知名 URL。这些类似于数据库中表的名称。对于可选的额外信用,使所有固定 URL 都可以从一个 URL 中发现。
后来……
了解如何设计好的 HTTP/REST API 的人也很短缺。不幸的是,我们看到许多尝试采用面向实体的 HTTP/REST 样式的 API 示例,但由于没有始终如一地遵循模型,因此未能实现所有好处。一些常见的错误是:
- 使用“本地标识符”而不是 URL 来编码实体之间的引用。如果 API 需要客户端替换 URI 模板中的变量来形成资源的 URL,那么它已经失去了 HTTP 统一接口价值的重要部分。构建对查询进行编码的 URL 是 URI 模板的唯一常见用途,它与 HTTP 作为统一接口的想法兼容。
我同意两者,但我看不到如何实现这一点。
所以这是场景:
- API 端点:
GET openapi.json / wadl / whatever-discovery-mechanism
/articles/ /articles/$id - only for Option 2 below ... (maybe for each entity operation in case of exhaustive discovery like openapi, but I'd want to keep it minimal for now)
GET /articles
{ data: [ { title: "Article 1", links: { self: "/articles/1", ... } } ] }
GET /articles/$id
DELETE /articles/$id
- ...
- 前端网址:
GET /site/articles
- 显示文章列表/表格的页面GET /site/articles/1
- 带有用于编辑该文章的表单的页面
导航到/site/articles
时,前端会知道调用/articles
API 端点——这是 Google 提到的“有限固定 url”之一。考虑到文章实体返回的链接,也可以删除/更新。通过客户端导航,前端还可以“重定向”到/site/articles/1
.
棘手的部分是当用户直接导航到/site/articles/1
- 页面如何知道调用/articles/$id
而不构建 URL 本身(或以某种方式翻译它)?
这些是我看到的选项:
- 构建 URL(这基本上是上面提到的“常见错误 1”)
// /site/articles/1 const apiUrl = '/articles/' + location.pathname.split('/')[3] // /articles/1
- 从发现链接构建 URL(先前选项的变体,仍然与 IMO 一样糟糕)
// /site/articles/1 const apiUrl = api.endpoints.articles + location.pathname.split('/')[3] // or replace or whatever // /articles/1
- 在前端 URL 中编码实体“self”链接
我对此的担忧是:// /site/articles/L2FydGljbGVzLzE= const apiUrl = atob(location.pathname.split('/')[3]) // /articles/1
- 有点丑
- 不安全(xsrf / 打开重定向 ...)
- 它强制前端无论如何构建 URL(只有它理解)
- 编码实体标识符(据我所知,它是“自我”链接),然后查找它
/articles
以调用返回的链接// /site/articles/L2FydGljbGVzLzE= const entityId = atob(location.pathname.split('/')[3]) const apiUrl = api.get(api.endpoints.articles) .first(article => article.links.self === entityId) .links.self // /articles/1
- 比3还要丑。
- 足够安全
- 乍一看似乎毫无意义...
解决方案
如果您担心用户通过键入 URL 直接导航到页面,那么这是固定的知名 URL 之一。很可能任何“可添加书签”的东西都会出现在该列表中。
这里的关键是短语“编码实体之间的引用”。这不是实体之间的链接,它是一个初始入口点,因此可以从头开始构建 URL。这是一种不灵活的做法,但作为入口点,您别无选择。当您浏览关系时,“常见错误”将在整个应用程序中嵌入“URL 构建”。即通过用户ID 对文章有一个“评论者”列表,并通过将路径耦合到文章页面中的用户来构建这些URL。
推荐阅读
- filehelpers - 有没有办法检索 FileHelpers Engine 正在解析的整行
- asynchronous - 使用带有 ListView.builder 的 FutureBuilder 初始化 App 并在每个 ListItem 中有一个 onClick?
- python - 在Python中满足条件时如何运行x命令y秒?
- android - 我如何自定义 android 工具栏形状
- angular - 为什么 source-maps 标志会影响 Angular 7 中的代码覆盖率报告?
- c - 为什么这种冒泡排序是错误的?
- python - 熊猫 fillna() 就地不使用 .loc
- scala - 如何避免可变集合的意外突变?
- android - 我的 AndroidManifest.xml 中的“.lifecycle-trojan”是什么
- javascript - 如何在 Kattis 问题解决中进行分行?