Проблемы с перенаправлением постоянных ссылок из-за того, что фрагмент после "#" не отправляется на сервер

РЕДАКТ: изменил заголовок темы, чтобы он соответствовал найденной проблеме, спасибо за ответы ниже

У меня наблюдается странное поведение с постоянными ссылками при работе над миграцией.

Моя проблема не в том, что внутренние ссылки не перенаправляют. Я просто тестирую это, вставляя 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 у меня следующее:

А вот так это выглядит в базе данных:

Но когда я ввожу это в адресную строку браузера:

оно перенаправляется на:

Вместо того, чтобы вести к:

Так что я вижу первый пост, но он не прокручивается ко второму, как должно быть.

Почему хеш #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, когда они использовали только фрагменты URL для маркировки ссылок на сообщения… вздох.

Я вижу три подхода, которые Discourse мог бы использовать для обхода этой проблемы (здесь я явно вхожу в область фантазий, так что наслаждайтесь поездкой):

  1. При загрузке страницы срабатывает JavaScript, распознаёт хэш-фрагмент в URI и использует его для обращения к серверу с целью повторного перенаправления в правильное место. Это работает, но приводит к двойному перенаправлению, и пользователь видит перезагрузку страницы.

  2. Discourse мог бы добавлять (на стороне сервера) тег id со старым импортированным post_id в HTML каждого сообщения. Таким образом браузер сохранил бы старый хэш-идентификатор и использовал его на перенаправленной странице, прокручивая к нужному месту. Основной недостаток: продвинутая прокрутка 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 (или в любое другое программное обеспечение).

Извините. Я не прочитал это достаточно внимательно. Я думал, что раньше использовал содержимое после хеша, но, похоже, я ошибался. Помню недавний случай, когда такие идентификаторы постов после хеша присутствовали, но, видимо, клиент хотел только перенаправления на уровне темы. Думаю, что для 301-перенаправлений попадания в нужную тему, скорее всего, достаточно.