Correção: o Discourse é renderizado como HTML sem estilo no navegador integrado do Facebook no iPhone

Resumo

Se o seu site Discourse parecer um HTML simples e sem estilo quando acessado por meio de um link no aplicativo do Facebook no iPhone — sem CSS, sem JavaScript, sem funcionalidade — a causa é a detecção de robôs do Discourse identificando incorretamente o navegador integrado do Facebook como um bot.

A correção é uma alteração de uma linha via console do Rails.


O sintoma

Usuários que clicam em links para o seu site Discourse a partir do aplicativo do Facebook no iPhone veem uma página HTML simplificada e sem estilo — essencialmente o layout de crawler/noscript. Nenhum JavaScript é executado, então recursos como grades de imagens, lightboxes e players de mídia não funcionam. Os mesmos links funcionam corretamente no Safari, Chrome e no navegador integrado do Facebook no Android e iPad.


A causa

O navegador integrado do Facebook no iPhone se identifica com uma string de user agent contendo a palavra facebook, por exemplo:

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

A detecção de robôs do Discourse (CrawlerDetection) verifica os user agents contra a configuração do site crawler_user_agents, cujo valor padrão inclui facebook:

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

Isso faz com que o Discourse sirva ao navegador integrado do Facebook o layout estático do crawler em vez do aplicativo Ember completo — mesmo sendo um navegador real sendo usado por uma pessoa real.

Você pode confirmar que isso está acontecendo verificando seu log de acesso do nginx para solicitações desse navegador e notando que o tamanho da carga de resposta é dramaticamente menor que o normal (geralmente ~5KB vs ~35KB para uma página de tópico completa).


A correção

Adicione MetaIAB à configuração do site crawler_check_bypass_agents. Essa configuração foi projetada especificamente para isentar user agents do tratamento de robôs, mesmo quando correspondem à lista de robôs.

Observação: crawler_check_bypass_agents é uma configuração de site oculta e não aparece na interface administrativa padrão. O console do Rails é necessário.

Via o console do Rails

SiteSetting.crawler_check_bypass_agents = "MetaIAB"

Se a configuração já tiver um valor (por exemplo, cubot), anexe com um separador de pipe:

SiteSetting.crawler_check_bypass_agents = "cubot|MetaIAB"

A alteração entra em vigor imediatamente — nenhuma reinicialização é necessária.


Por que isso funciona

O método CrawlerDetection.crawler? usa três configurações em combinação:

  1. non_crawler_user_agents — se o UA corresponder a esta lista, ele pode ser um navegador real
  2. crawler_user_agents — se também corresponder a esta lista, é tratado como um robô
  3. crawler_check_bypass_agents — se corresponder a esta lista, é isento do tratamento de robôs, independentemente

O UA do navegador integrado do Facebook contém Safari, que corresponde a non_crawler_user_agents. Também contém facebook, que corresponde a crawler_user_agents. Adicionar MetaIAB — uma string exclusiva do UA do navegador integrado do Facebook — a crawler_check_bypass_agents faz com que o Discourse sirva o aplicativo completo a ele.


Por que Android e iPad não são afetados

  • Android: O navegador integrado do Facebook no Android envia um user agent diferente que não contém facebook, então ele passa pela detecção de robôs sem problemas.
  • iPad: O navegador integrado do Facebook no iPad também ativa o layout do crawler, mas como o iPad reporta uma window.innerWidth ampla (~1180px), o Discourse serve o layout de desktop, que acaba sendo renderizado adequadamente. A viewport estreita do iPhone (~414px) ativa o layout móvel, que no modo crawler é completamente não funcional.

Nota adicional: inundação do meta-webindexer

Separadamente, o indexador da web do Facebook (meta-webindexer/1.1) pode enviar um volume muito alto de solicitações ao seu site — potencialmente milhares por hora — todas direcionadas à página inicial. Diferentemente do meta-externalagent (que lida com pré-visualizações de links OG e deve permanecer desbloqueado), o meta-webindexer parece não ter nenhum propósito útil para a maioria das instalações do Discourse.

Se você observar esse tráfego em seus logs, pode bloqueá-lo no nível do nginx adicionando-o à sua configuração de bloqueio de bots:

"~*meta-webindexer" 1;

O meta-externalagent deve permanecer permitido, pois é responsável por extrair metadados OG quando links são compartilhados no Facebook.

2 curtidas

Obrigado @shortmort37. Fiz um PR para alterar o padrão no core para incluir o MetaIAB:

5 curtidas