Исправление: Discourse отображается как нестилизованная HTML-страница во встроенном браузере Facebook на iPhone

Резюме

Если ваш сайт Discourse при доступе через ссылку в приложении Facebook на iPhone отображается как обычный HTML без стилей — без CSS, без JavaScript и без функционала — причина заключается в ошибке определения роботов в Discourse, которая неверно идентифицирует встроенный браузер Facebook как бота.

Исправление заключается в однострочном изменении через консоль Rails.


Симптомы

Пользователи, переходящие по ссылкам на ваш сайт Discourse из приложения Facebook на iPhone, видят упрощённую страницу HTML без стилей — по сути, макет для роботов или тег noscript. JavaScript не выполняется, поэтому такие функции, как сетки изображений, лайтбоксы и медиаплееры, не работают. Те же ссылки корректно работают в Safari, Chrome, а также во встроенном браузере Facebook на Android и iPad.


Причина

Встроенный браузер Facebook на iPhone определяет себя строкой user-agent, содержащей слово facebook, например:

Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 
(KHTML, like Gecko) Mobile/23D8133 Safari/604.1 MetaIAB Facebook

Определение роботов в Discourse (CrawlerDetection) проверяет user-agent на соответствие настройке сайта crawler_user_agents, значение по умолчанию которой включает facebook:

rss|bot|spider|crawler|facebook|archive|wayback|ping|...

Из-за этого Discourse отдаёт встроенному браузеру Facebook статический макет для роботов вместо полного приложения Ember, хотя на самом деле это настоящий браузер, используемый реальным человеком.

Вы можете убедиться в этом, проверив лог доступа nginx на наличие запросов от этого браузера и заметив, что размер ответа значительно меньше обычного (обычно ~5 КБ против ~35 КБ для полной страницы темы).


Исправление

Добавьте MetaIAB в настройку сайта crawler_check_bypass_agents. Эта настройка специально предназначена для исключения user-agent из обработки как роботов, даже если они совпадают со списком роботов.

Примечание: crawler_check_bypass_agents — это скрытая настройка сайта, которая не отображается в стандартном интерфейсе администратора. Для её изменения требуется консоль Rails.

Через консоль Rails

SiteSetting.crawler_check_bypass_agents = "MetaIAB"

Если настройка уже содержит значение (например, cubot), добавьте новое значение через разделитель |:

SiteSetting.crawler_check_bypass_agents = "cubot|MetaIAB"

Изменение вступает в силу немедленно — перезапуск не требуется.


Почему это работает

Метод CrawlerDetection.crawler? использует три настройки в сочетании:

  1. non_crawler_user_agents — если UA соответствует этому списку, это может быть настоящий браузер
  2. crawler_user_agents — если он также соответствует этому списку, он обрабатывается как робот
  3. crawler_check_bypass_agents — если он соответствует этому списку, он исключается из обработки как робот независимо от других условий

User-agent встроенного браузера Facebook содержит Safari, который соответствует non_crawler_user_agents. Также он содержит facebook, который соответствует crawler_user_agents. Добавление MetaIAB — строки, уникальной для user-agent встроенного браузера Facebook, — в crawler_check_bypass_agents заставляет Discourse отдавать ему полное приложение.


Почему Android и iPad не затронуты

  • Android: встроенный браузер Facebook на Android отправляет другой user-agent, не содержащий facebook, поэтому он проходит проверку на роботов без проблем.
  • iPad: встроенный браузер Facebook на iPad также вызывает отображение макета для роботов, но поскольку iPad сообщает широкое значение window.innerWidth (~1180 пикселей), Discourse отдаёт десктопный макет, который оказывается достаточно функциональным. Узкое окно просмотра iPhone (~414 пикселей) вызывает отображение мобильного макета, который в режиме роботов полностью неработоспособен.

Дополнительное примечание: нашествие meta-webindexer

Отдельно стоит отметить, что веб-индексатор Facebook (meta-webindexer/1.1) может отправлять на ваш сайт очень большой объём запросов — возможно, тысячи в час — все они направлены на главную страницу. В отличие от meta-externalagent (который обрабатывает предпросмотры ссылок OG и должен оставаться разблокированным), meta-webindexer, по-видимому, не выполняет никакой полезной функции для большинства установок Discourse.

Если вы наблюдаете такой трафик в своих логах, вы можете заблокировать его на уровне nginx, добавив его в конфигурацию блокировки ботов:

"~*meta-webindexer" 1;

meta-externalagent должен оставаться разрешённым, так как он отвечает за извлечение метаданных OG при публикации ссылок в Facebook.

2 лайка

Спасибо @shortmort37. Я создал PR, чтобы изменить значение по умолчанию в ядре и включить MetaIAB:

6 лайков

Эта тема была автоматически закрыта через 14 часов. Новые ответы больше не принимаются.