由于“#”后的片段未发送到服务器,导致固定链接重定向出现问题

编辑:根据下文回答所发现的问题,已修改主题标题,感谢大家

我的迁移工作中,固定链接出现了奇怪的行为。

我的问题不是内部链接无法重定向。我只是尝试将 URL 粘贴到浏览器的地址栏中。

以下是我测试中期望发生的两个重定向:

这是一个帖子重定向,应重定向到第二个帖子,如下所示:

这是一个主题重定向,应跳转到:

我知道我的规范化处理工作正常。我的正则表达式是:

/(?:.*)(\/)(?<topicid>\d*.)-(.[^\/#\?]*)(?<parm>\?(\w*)[=](?<start>\d+))?(?:\/)?(\D+(\/)?)?(?<postid>\d+)?(?:\/)?/normalized.\k<topicid>.\k<postid>

我在 rails 控制台中进行了检查:

irb(main):069:0> Permalink.normalize_url('https://community.suitecrm.com/languages/17978-why-two-italian-language-packs#16249')
=> "normalized.17978.16249"

irb(main):068:0> Permalink.normalize_url('https://community.suitecrm.com/languages/17978-why-two-italian-language-packs')
=> "normalized.17978."

这正是我所期望的。我的 Permalinks 表中包含以下内容:

从数据库中查看的结果如下:

但是,当我在浏览器地址栏中输入以下 URL 时:

它被重定向到了:

而不是它本应跳转到的:

因此,我看到的是第一个帖子,并没有像预期那样滚动到第二个帖子。

既然我的规范化处理已经移除了它,为什么 #16249 这个哈希值又被加回来了?

另一种揭示这种不一致(尽管有些人为)的方式是尝试在浏览器地址栏中进行以下重定向:

https://community.suitecrm.com/normalized.17978.
正确重定向到:
Reports disappeared - 💬 General Discussion - SuiteCRM

Why two Italian language packs? - #2 by roberto - Translation and Language Packs - SuiteCRM
正确重定向到
Reports disappeared - #2 by erevodifosin - 💬 General Discussion - SuiteCRM

那么,为什么通过正常流程时却无法正常工作呢?

永久链接仅适用于传入链接,描述中已明确说明。

您需要修正内部链接。

我在帖子开头已经提到过,情况并非如此,我并没有点击自己论坛中的链接。

但也许我还没有完全理解这里所说的“内部链接”具体指什么,能否请您进一步解释一下?如果我在浏览器的地址栏中粘贴一个 URL,这怎么能算作内部链接呢?

URL 片段标识符(即 # 及其后的所有内容)不会被浏览器发送到服务器,因此不能将其用作重定向的一部分。

你这么一说,确实有道理……但还挺让人沮丧的。

我想这完全排除了从我的旧论坛进行正确的帖子级重定向的可能性,因为它们使用 # 来实现这一点 :sob:

这在迁移中是常见的限制吗?这是 Kunena 软件,我想这很普遍,我敢打赌其他人也使用哈希值来链接帖子……

我一直在脑子里琢磨这件事。这真是一个令人恼火的限制。我想根本的错误早在很久以前就犯了,是 Kunena 论坛的设计师在仅使用片段来标记帖子链接时造成的……唉。

我看到 Discourse 可以采用三种方法来绕过这个问题(我现在明显是在异想天开,请尽情享受这段旅程):

  1. 页面加载时 JavaScript 介入,识别 URI 中存在哈希片段,并调用服务器重新重定向到正确位置。这可行,但会导致双重重定向,用户会看到页面重新加载。

  2. Discourse 可以在服务器端为每个帖子的 HTML 添加一个带有旧导入 post_idid 标签。这样浏览器会传递旧的哈希 ID,并在重定向后的页面中使用它,滚动到底部。主要限制是:Discourse 的精美滚动功能(帖子仅在滚动到它们时才加载)使得此方案不够完善。

  3. 上述方法的混合:Discourse 在服务器端构建旧导入 post_id 与新 post_number 之间的对应表,并在页面加载时将其发送到客户端。客户端的 JavaScript 识别 URI 中的哈希,使用该表转换哈希,并利用自身的滚动功能向下滚动到正确的帖子。

这将需要大量工作来实现,并且会带来性能损失。不过,它确实能够实现完美的迁移……

这些并非完整的解决方案,因为除非用户已在 Discourse 中,否则重定向仍无法生效。外部链接很少能以此方式到达。

我目前对内部/外部重定向的处理方式如下:

我的旧网站位于
https://suitecrm.com/suitecrm/forum/,新网站位于
https://community.suitecrm.com/

当迁移后的服务器上线时,我们会从旧地址到新地址执行网关重定向。

我保留内部链接不变,仍以 https://suitecrm.com/suitecrm/forum/ 开头。当有人点击这些链接时,从实际角度来看这属于外部链接。但随后会发生我们的网关重定向,请求会重新进入 Discourse,此时永久链接应能正常生效。

对吗?我还没有实际测试过……我想如果我们希望使用相同的域名和文件夹,这可能无法实现,但我们并不需要这样做。

你需要做的是使用固定链接重定向。

我经常创建类似 /oldpost/POST_ID 的固定链接,然后编写固定链接重定向规则,将 /forum./category/someslug#1234 重写为使用这些链接。

您提到的“固定链接重定向”是指站点设置中的“固定链接规范化”吗?

哎呀!是的。抱歉。我的脑子当时太困了。

好的 :slight_smile:

但我正在使用固定链接规范化(参见我的首帖)。只有哈希部分永远不会发送到服务器,因此除非有某种客户端 JavaScript 在施展魔法,否则一个仅使用哈希作为帖子级链接的论坛,在重定向方面,永远无法被正确迁移到 Discourse(或任何其他软件)。

抱歉。我没读得够仔细。我以为我之前用过哈希后面的内容,但看来我记错了。我记得最近有个案例,那些哈希帖子 ID 确实存在,但我想客户端只需要主题级别的跳转。我认为对于 301 重定向来说,最终能到达正确的主题应该就足够了。