在单页应用程序中创建临时 URL

IT技术 javascript reactjs url redux react-router
2021-05-12 14:31:26

在我基于 React 的单页应用程序中,我的页面分为两个窗格。

左窗格:过滤器面板。

右窗格:网格(包含通过应用过滤器的数据的表格)

总之,我有一个与 amazon.com 非常相似的应用程序。默认情况下,当用户在浏览器中点击应用程序的根端点 (/) 时,我会从服务器获取过去 7 天的数据并将其显示在网格中。

过滤器面板有几个过滤器(例如时间过滤器来获取落在指定时间间隔内的数据,ID 来搜索具有特定 id 的数据等)和一个附加在过滤器面板标题中的搜索按钮。点击搜索按钮通过在帖子表单正文中提供选定的过滤器来对服务器进行帖子调用,服务器返回与传递的过滤器匹配的数据,我的前端应用程序显示从网格内的服务器返回的数据。

现在,当有人点击过滤器面板中的搜索按钮时,我想在 URL 的查询参数中反映选定的过滤器,因为这将帮助我与我网站的其他用户共享这些 URL,以便他们可以看到我应用的过滤器和仅查看与这些过滤器匹配的网格内的数据。

这里的问题是,如果在搜索按钮单击时,我使用带有查询参数的 http get,由于不同浏览器对 URL 长度的限制,我最终会破坏应用程序。

请建议我创建此类 URL 的正确解决方案,这将帮助我在过滤器面板中设置选定的过滤器,而不会对我的应用程序造成任何副作用。

可能的解决方案:考虑到由于不同浏览器的URL长度限制,我们不能直接在查询参数中添加纯字符串(注:规范不限制HTTP Get请求的长度,但不同浏览器实现了自己的限制),我们可以使用诸如消息摘要或哈希之类的东西(将任意长度的输入转换为固定长度的输出)并将其保存在数据库中,以便服务器理解请求并返回内容。这只是一个想法,我不确定这是否是这个问题的理想解决方案。

其他频繁使用的网站的行为:

  • amazon.com, newegg.com ->使用散列网址。
  • kayak.com ->因为他们有很好定义的关键字,所以他们使用简短的形式,如 INDIA 表示 INDIA,BLR 表示 Bangalore 等,并将其与否定逻辑相结合,以进一步优化最大 url 长度。未选中,但理想情况下会在大量选择过滤器后中断。
  • flipkart.com ->将字符串直接附加到查询参数并在超出限制后中断。验证了这一点。
2个回答

针对@cauchy 的回答,我们需要区分散列加密

散列

哈希必然是不可逆的。为了将哈希映射到特定的过滤器组合,您需要

  1. 为每个请求对服务器上的每个过滤器排列进行散列,以尝试匹配请求的散列(计算密集型)或
  2. 在服务器上存储哈希映射以过滤组合(内存密集型)。

对于绝大多数情况,选项 1 会太慢。根据过滤器和选项的数量,选项 B 可能需要相当大的地图,但它仍然是您的最佳选择。

加密

在这种方案中,服务器将其公钥发送给客户端,然后客户端可以使用它来加密其过滤器选项。然后服务器将使用其私钥解密加密数据。这很好,但是您的加密数据不会是固定长度的因此,随着选择更多选项,您会遇到相同的参数长度不确定问题。

因此,为了确保您的 URL 对于任意数量的过滤器和选项都是简短的,您需要在服务器上维护哈希->选择的映射。

我们应该如何处理永久链接和临时链接?

你在上面的评论中提到

如果我们使用一些持久存储来保存这个散列到实际过滤器之间的映射,我们理想情况下希望将长期存在的“永久链接”与短期存在的临时 URL 分开,并使用这种理解来有效地使短期散列过期。

您可能在服务器上有一个服务来处理您在应用程序中支持的所有过滤器。这里的技巧是让该服务也管理哈希图。随着更多过滤器和选项的添加/删除,服务将需要重新散列过滤器选择的每个排列。

如果您需要对永久链接的强大支持,那么无论何时删除过滤器或选项,您都需要维护“过期”哈希并将它们的映射更改为指向合理的替代哈希。

我们什么时候更新数据库中的哈希值?

有很多选择,但我通常更喜欢build time如果您使用的是 Jenkins、Travis、AWS CodePipeline 等 CI 解决方案,那么您可以添加一个构建步骤来更新您的数据库。基本上,你会...

  1. 保留所有现有支持的过滤器的持久记录。
  2. 在构建时,检查是否有任何新过滤器。如果是这样...
    1. 将这些过滤器添加到步骤 1 的记录中。
    2. 散列所有新的过滤器排列(仅包含您的新过滤器的那些)并将它们存储在散列数据库中
  3. 检查是否已删除任何过滤器。如果是这样...
    1. 从步骤 1 的记录中删除这些过滤器。
    2. 查找包含这些过滤器的排列的所有散列,或者...
      • 从数据库中删除这些哈希(弱永久链接),或
      • 将该散列指向数据库中的一个合理的替代散列(强固定链接)

让我们分析您的问题和可能的解决方案。问题:您需要一个包含过滤器信息的 URL,这样当您共享该 URL 时,用户不会登陆任意页面。

解决方案:

1) 使用 URL 附加过滤器。为此,您需要缩短过滤器类型的键和过滤器的值,以便每个过滤器的 URL 长度不会超过太多。

缺点:这不是最可靠的解决方案,因为过滤器的数量增加 URL 长度必须增加没有其他选择。

2) 使用 URL 附加过滤器应用(哈希)的唯一键。为此,您需要对服务器和客户端都进行一些更改。在客户端,您将需要一种编码算法,将过滤器应用于唯一哈希。在服务器端,您将需要解码算法,将唯一哈希转换为应用的过滤器。所以现在客户端,每当这样的 URL 被命中时,您可以进行 POST api 调用,该调用采用此散列为您提供应用的过滤器数组,或者在客户端只放置转换此散列的逻辑。执行所有这些操作componentWillMount以避免任何副作用。

我认为第二个解决方案在几乎所有情况下都是可扩展且高效的。