Комментарии с ошибкой встраивания

TL;DR: Discourse выдаёт «Error Embedding» независимо от того, какие хосты я добавляю в настройки встраивания. У меня есть опубликованный сайт на foo.com, который встраивает комментарии с форума Discourse на forum.foo.com — это работает отлично. При переходе, например, на https://foo.com/blog/2019-11-22/foo-0.9.6-released, встроенные комментарии отображаются корректно. В этом случае код скрипта для встраивания в исходном коде страницы выглядит так:

<div id='discourse-comments'></div>
<script type="text/javascript">
  DiscourseEmbed = { discourseUrl: 'https://forum.foo.com/', discourseEmbedUrl: 'https://foo.com/blog/2019-11-22/foo-0.9.6-released' };

  (function() {
    var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
    d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
  })();
</script>

Также у меня есть тестовая версия сайта, запущенная локально на localhost, где возникают проблемы с встраиванием — вместо комментариев в HTML, генерируемом и возвращаемом форумом, постоянно появляется сообщение «Error Embedding». То есть в области встраивания в правом верхнем углу я вижу логотип форума и ссылку на него, но вместо списка комментариев отображается только это сообщение об ошибке.

При переходе, например, на http://localhost:1313/blog/2019-11-22-foo-0.9.6-released/, что соответствует той же странице на продакшене, код скрипта для встраивания в исходном коде страницы выглядит так:

<div id='discourse-comments'></div>
<script type="text/javascript">
  DiscourseEmbed = { discourseUrl: 'https://forum.foo.com/', discourseEmbedUrl: 'http://localhost:1313/blog/2019-11-22-foo-0.9.6-released/' };

  (function() {
    var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
    d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
  })();
</script>

Я пробовал как с завершающим слэшем в параметре discourseEmbedUrl, так и без него — разницы нет.

У меня нет прямого доступа к серверу, на котором работает форум, но я зашёл в админ-панель форума и попытался добавить несколько разрешённых хостов в настройках встраивания. Текущие настройки для работающего продакшн-сайта следующие:

«Allowed Hosts», «Class Name», «Path Whitelist», «Post to Category»

foo.com, <пусто>, /blog/.*, blog

Что я добавил, чтобы это заработало для моей локальной тестовой версии сайта:

«Allowed Hosts», «Class Name», «Path Whitelist», «Post to Category»

localhost, <пусто>, /blog/.*, blog
localhost:1313, <пусто>, /blog/.*, blog
<мой внешний/публичный IP-адрес, видимый сервером форума>, <пусто>, /blog/.*, blog
<мой внешний/публичный IP-адрес, видимый сервером форума>:1313, <пусто>, /blog/.*, blog

Но ничего из этого не помогло — я всё равно получаю то же сообщение «Error Embedding».

Мне не хочется лезть в исходный код и пытаться отлаживать это вручную; я бы предпочел получить информацию о том, что именно проверяет Discourse при принятии решения о генерации этого сообщения об ошибке. Может ли кто-нибудь объяснить это и подсказать, как исправить проблему? Это должно быть довольно просто, но Discourse ведёт себя здесь как чёрный ящик.

Я прочитал всю статью Embed Discourse comments on another website via Javascript, но там нет более полезной информации.

Возможно, стоит использовать topicID, как указано по ссылке: Embed Discourse comments on another website via Javascript.

Меня бы не удивило, если бы «localhost» был запрещён по разным причинам. Это заставило бы ваш сервер форума встраивать себя самого. :dizzy_face:

Если вы используете Hugo, возможно, стоит загружать шаблон комментариев условно или явно передавать baseURL в шаблоне, чтобы даже во время разработки загружался discourseEmbedUrl: 'https://foo.com/blog/2019-11-22/foo-0.9.6-released'.

@maiki Большое спасибо за то, что нашли время ответить.

Использование topicId, как описано в руководстве, не решает проблему и не меняет симптомов. URL-адрес запроса, конечно, меняется на https://forum.foo.com/embed/comments?topic_id=2279, но возвращается точно такое же сообщение об ошибке.

Я также попробовал изменить discourseEmbedUrl на https://foo.com/blog/2019-11-22/foo-0.9.6-released, но, к сожалению, это тоже не помогло.

Даже если это сделано намеренно, это должно быть задокументировано. Например, блокируются ли запросы с сайта на localhost, даже если он явно указан в списке разрешённых хостов? Discourse проверяет поле Referrer в HTTP-запросе или что именно используется для генерации этой ошибки? Это нужно обязательно прояснить, потому что на данный момент я не нашёл ничего, что объясняло бы, почему это не работает :slight_smile:

Какое сообщение об ошибке? Есть ли что-нибудь в консоли разработчика?

localhost — это не доменное имя, а имя хоста.

Не уверен, что имеет смысл объяснять это в руководстве по встраиванию, но хотя бы у нас есть эта тема для справки! :slight_smile:

Нет, в консоли разработчика на локальном клиенте/браузере ошибок нет. HTML успешно возвращается с сервера форума, я вижу его без проблем в инструментах разработчика.

Вот как это должно выглядеть, когда всё работает (некоторый текст зацензурен):

А вот как это выглядит в данном случае (некоторый текст зацензурен):

То есть сервер форума просто возвращает код 400 и сообщение «Ошибка встраивания» вместо правильного содержимого.

Конечно, но, как вы предположили, возможно, Discourse блокирует такие запросы от рефереров, которые приходят с localhost. Я понимаю, что «localhost» — это не доменное имя, а имя хоста. Это согласуется с тем фактом, что в настройках встроенного форума в разделе «Разрешённые хосты» указываются именно хосты.

Я прекрасно понимаю, что такое localhost, это не проблема.

Объяснять, что такое localhost? Нет, это не нужно. Когда я говорил, что нам нужно прийти к выводу, почему у меня это не работает, и что это должно быть задокументировано, я имел в виду в целом, почему это, возможно, не должно работать, если это так. Опять же, на данный момент ничто не указывает на то, что такое поведение является ожидаемым.

Ваш сайт Discourse настроен на «Требуется вход в систему»?

Параметр «Требуется вход» в разделе «Вход» снят, поэтому нет, он не настроен.

Размышляя вслух: в чем разница между запросом с моего локального сайта разработки и запросом с продакшн-сайта, так это не так много. Это должно быть просто HTTP-ссылка и, конечно, источник HTTP-запроса. Кроме этого, я использую один и тот же браузер для обоих сайтов.

Вы можете проверить, является ли проблема на стороне хоста, попробовав встроить его на другой, действующий домен (возможно, поддомен одного из ваших).

Размышляя вслух: если я скажу Discourse принимать «localhost», он будет искать его на localhost, который является сервером Discourse.

Удачи! Я не знаю, что происходит. :slight_smile:

Я понимаю вашу логику. В этот момент становится интересно узнать, на что именно он обращает внимание при определении доступа и почему выдает именно это сообщение об ошибке.

К слову, проблема в том, что он (Discourse, отвечая на встроенный запрос) возвращает HTTP-код ответа 400, что просто означает «Неверный запрос». Если бы дело было в недопустимом хосте или чём-то подобном, я бы ожидал код 401 («Неавторизовано») или аналогичный, но это не так. Это говорит о том, что проблема не связана с авторизацией или разрешёнными хостами. Однако не исключено, что просто код бэкенда не формирует корректный HTTP-код ответа.

Наверняка кто-то должен знать, возможно ли вообще встраивать комментарии с домена forum.foo.com на локальный сайт для разработки? Я не вижу ничего, что запрещало бы это (например, через настройку разрешённых хостов), но раз это не работает, то ситуация довольно неясна.

Похоже, что происходит что-то более серьёзное.
Заголовки X-Frame-Options установлены в значение ALLOWALL.
Но ALLOWALL не является допустимым значением, см. X-Frame-Options header - HTTP | MDN
При попытке встроить комментарии я получаю следующую ошибку: «При загрузке обнаружен некорректный заголовок X-Frame-Options: «ALLOWALL» не является допустимым директивой».
Комментарии загружаются только при использовании topicId. Однако я полагаю, что это связано с тем, что при простом встраивании комментариев не требуются полные права доступа.

Спасибо за сообщение об ошибке. В каком браузере возникает ошибка? Актуальна ли версия вашего браузера?

Это в Firefox, и он обновлён. Я проверил Chrome — он не выдаёт ошибок, но просто не работает.

На случай, если кому-то интересно: я подробно описал свой случай этой проблемы ранее. И, по какой-то причине, внедрение комментариев сработало безупречно, когда мы наконец опубликовали сайт.

То есть, проблема и симптомы, которые я описывал ранее, возникали, когда я запускал веб-сайт, внедряющий комментарии с forum.domain.com, на своей локальной системе, такой как localhost или аналогичной. Но когда я опубликовал сайт на domain.com, он заработал сразу.

Как я уже говорил ранее, я не могу найти в настройках форума ничего, что запрещало бы доступ к комментариям или их внедрение из источников, отличных от domain.com. Поэтому, почему это не работало, остаётся загадкой для меня. Должно быть что-то в коде Discourse, что это предотвращает, но что именно — я не знаю.

Я пытался воспроизвести эту проблему, но пока не смог. При использовании стандартного скрипта встраивания комментарии отображаются у меня без ошибок как в последнем Chrome, так и в Firefox (работающих на Ubuntu).

Также стоит проверить, что вы создали запись хоста в разделе «Администрирование / Настройка / Встраивание» вашего сайта. Я упоминаю об этом, потому что при тестировании у меня возникала ошибка, так как я не заполнил настройку «Имя пользователя для создания темы» и не сохранил параметры встраивания.

У меня была похожая проблема, и я решил её, изменив параметр «Разрешённые хосты» в разделе Администрирование > Настройка > Встраивание: заменил example.com на www.example.com, и всё заработало. Мой форум установлен на subdomain.example.com, возможно, именно из-за этого возникали проблемы.

В любом случае, не уверен, поможет ли это вам, но надеюсь, что да!