パーマリンクのリダイレクトで問題:「#」後のフラグメントがサーバーに送信されないため

編集:以下の回答のおかげで問題の原因が判明したため、トピックのタイトルをそれに合わせて変更しました

マイグレーション作業中に、パーマリンクで奇妙な動作が発生しています。

私の問題は、内部リンクのリダイレクトが機能しないというものではありません。単にブラウザのアドレスバーに URL を貼り付けてテストしているだけです。

私がテストで意図しているリダイレクトは以下の 2 つです。

これは投稿のリダイレクトであり、以下のように 2 番目の投稿にリダイレクトされるはずです。

これはトピックのリダイレクトであり、以下へ移動するはずです。

私の正規化処理は正常に機能していることは分かっています。私の正規表現は以下の通りです。

/(?:.*)(\/)(?<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 に以下を入力すると

以下へリダイレクトされてしまいます。

本来あるべき先は以下の通りです。

そのため、最初の投稿が表示され、本来あるべき 2 番目の投稿へスクロールされません。

なぜ、正規化で削除されたはずの #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 がこの問題を回避するために考えられる 3 つのアプローチがあります(ここからは完全に願望的な領域に入りますが、お付き合いください)

  1. ページ読み込み時に JavaScript が起動し、URI にハッシュフラグメントがあることを認識して、サーバーを呼び出し、適切な場所へリダイレクトする。機能はしますが、二重リダイレクトが発生し、ユーザーはページが再読み込みされるのを見てしまいます。

  2. Discourse がサーバーサイドで、各投稿の HTML に、インポートされた古い post_id を持つ id タグを追加する。これにより、ブラウザは古いハッシュ 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 をそれらのリンクに書き換えるパーマリンクリダイレクトを設定しています。

「パーマリンクのリダイレクト」とは、サイト設定のpermalink normalizationsのことをおっしゃっているのでしょうか?

おっと!はい、すみません。私の頭、もう限界でした。

はい :slight_smile:

ただし、私はパーマリンクの正規化を使用しています(最初の投稿を参照してください)。ハッシュ部分のみがサーバーに送信されることはありません(決して)。クライアント側の JavaScript が何らかの魔法を働かせていない限り、投稿レベルのリンクにハッシュのみを使用するフォーラムは、リダイレクトの観点から Discourse(または他のソフトウェア)へ正しく移行されることは決してありません。

すみません。十分に注意して読んでいませんでした。ハッシュ以降の部分を以前に使ったことがあると思ったのですが、それは間違いのようです。最近、そのようなハッシュ付きの投稿IDが存在したケースを思い出しますが、クライアントがトピックレベルのリダイレクトのみを望んでいたのだと思います。301リダイレクトで正しいトピックに到達できれば、それで十分だと思われます。