【问题标题】:Creating temp URLs in single page applications在单页应用程序中创建临时 URL
【发布时间】:2018-03-19 16:28:18
【问题描述】:

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

左窗格:过滤器面板。

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

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

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

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

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

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

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

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

  • amazon.com、newegg.com -> 使用散列网址。
  • kayak.com -> 因为他们有非常明确的关键字,他们使用 短格式,例如 IN 代表印度,BLR 代表班加罗尔等,并结合 这与否定逻辑进一步优化最大 url 长度。不是 已检查,但理想情况下,这会在选择大量过滤器后中断。
  • flipkart.com -> 将字符串直接附加到查询参数和中断 突破限制后。验证了这一点。

【问题讨论】:

  • 你真的遇到过这个问题吗?我相信现代浏览器中的 URL 长度几乎是无限的。
  • 因此,超过 2000 个字符的 URL 的问题似乎只影响 IE
  • 您的意思是说创建任何长度的临时 URL 都不成问题?我看到亚马逊创建哈希并将这些哈希附加到 URL 中,而不是以纯文本格式附加选定的过滤器。
  • 如果您遇到的问题是由于查询字符串太长而导致对服务器的请求引发错误,您应该使用请求正文而不是查询参数发送数据。

标签: javascript reactjs url redux react-router


【解决方案1】:

响应@cauchy's answer,我们需要区分散列加密

散列

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

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

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

加密

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

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

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

你在your comment above中提到

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

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

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

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

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

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

【讨论】:

  • 感谢卢克对这一点的精彩解释/总结。
  • 正如我之前提到的,考虑到这是 webapps 的一个非常普遍的要求,我很惊讶没有关于这个的文章。
  • 感谢 Luke 添加解释 @lokesh 尝试该方法。一旦完成,让我们在此合并一篇中等文章。
  • 卢克,这里还有一件事是:我不想最终为传递的相同字符串(相同的过滤器)创建一个新的哈希。我们如何在我们的服务中确保这一点?当数据库增长时,搜索和查找现有条目将以搜索操作为代价。
  • @LokeshAgrawal 请参阅添加的关于何时更新哈希的部分。
【解决方案2】:

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

解决方案:

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

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

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

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

【讨论】:

  • 我也想到了第二种解决方案,需要排序的问题 1. 如果我们使用一些持久性存储来保存这个哈希到实际过滤器之间的映射,我们理想地想要隔离长寿命“永久链接”来自短暂的临时 url,并使用这种理解来有效地使短暂的哈希过期。 2. 通过查看 url 本身(例如 /temp/filter)应该很明显,哪些 url 是短暂的,哪些是永久的。 3.或者我们应该做一些类似gitlab的事情吗?除非您单击永久链接,否则无法保证会有链接。
  • 这是一个非常普遍的问题,我认为有很多文章和开源解决方案可以解决这个问题。您是否有任何文章/开源项目对此进行了详细描述?
  • Lokesh 我没有找到任何与此相关的链接。对于您提到的问题 1) 无需为此使用持久存储,我们可以在需要时使用加密和解密逻辑,并使用一些查询字符串(如 xyx.com/path-to-product?f={hash})传递哈希。无需存储映射
  • 我认为没有这样的加密算法可用。
  • @LokeshAgrawal 打算发表评论,但时间越来越长。留下答案以添加到讨论中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多