Fix: Discourse wird im in-App-Browser von Facebook auf iPhone als ungestyltes HTML gerendert

Zusammenfassung

Wenn Ihre Discourse-Seite beim Zugriff über einen Link in der Facebook-App auf dem iPhone wie einfacher, ungestalteter HTML-Code aussieht – ohne CSS, ohne JavaScript, ohne Funktionalität –, liegt die Ursache daran, dass die Crawler-Erkennung von Discourse den In-App-Browser von Facebook fälschlicherweise als Bot identifiziert.

Die Lösung besteht aus einer einzeiligen Änderung über die Rails-Konsole.


Das Symptom

Benutzer, die über die Facebook-App auf dem iPhone auf Links zu Ihrer Discourse-Seite klicken, sehen eine reduzierte, ungestaltete HTML-Seite – im Wesentlichen das Crawler/Noscript-Layout. Kein JavaScript wird ausgeführt, sodass Funktionen wie Bildraster, Lightboxen und Media-Player nicht funktionieren. Dieselben Links funktionieren in Safari, Chrome sowie im In-App-Browser von Facebook auf Android und iPad einwandfrei.


Die Ursache

Der In-App-Browser von Facebook auf dem iPhone identifiziert sich mit einer User-Agent-Zeichenkette, die das Wort facebook enthält, zum Beispiel:

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

Die Crawler-Erkennung von Discourse (CrawlerDetection) prüft User-Agents gegen die Site-Einstellung crawler_user_agents, deren Standardwert facebook enthält:

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

Dies führt dazu, dass Discourse dem In-App-Browser von Facebook das statische Crawler-Layout anstelle der vollständigen Ember-Anwendung ausliefert – obwohl es sich um einen echten Browser handelt, der von einer echten Person verwendet wird.

Sie können dies bestätigen, indem Sie Ihr Nginx-Zugriffsprotokoll auf Anfragen von diesem Browser prüfen und feststellen, dass die Größe der Antwortnutzlast deutlich kleiner als normal ist (typischerweise ~5 KB gegenüber ~35 KB für eine vollständige Themen-Seite).


Die Lösung

Fügen Sie MetaIAB zur Site-Einstellung crawler_check_bypass_agents hinzu. Diese Einstellung ist speziell dafür ausgelegt, User-Agents von der Crawler-Behandlung auszunehmen, selbst wenn sie mit der Crawler-Liste übereinstimmen.

Hinweis: crawler_check_bypass_agents ist eine versteckte Site-Einstellung und erscheint nicht in der standardmäßigen Admin-Oberfläche. Die Rails-Konsole ist erforderlich.

Über die Rails-Konsole

SiteSetting.crawler_check_bypass_agents = "MetaIAB"

Wenn die Einstellung bereits einen Wert hat (z. B. cubot), fügen Sie ihn mit einem Pipe-Trennzeichen hinzu:

SiteSetting.crawler_check_bypass_agents = "cubot|MetaIAB"

Die Änderung tritt sofort in Kraft – ein Neustart ist nicht erforderlich.


Warum dies funktioniert

Die Methode CrawlerDetection.crawler? verwendet drei Einstellungen in Kombination:

  1. non_crawler_user_agents – wenn der UA mit dieser Liste übereinstimmt, könnte es sich um einen echten Browser handeln
  2. crawler_user_agents – wenn er auch mit dieser Liste übereinstimmt, wird er als Crawler behandelt
  3. crawler_check_bypass_agents – wenn er mit dieser Liste übereinstimmt, wird er unabhängig davon von der Crawler-Behandlung ausgenommen

Der User-Agent des In-App-Browsers von Facebook enthält Safari, was mit non_crawler_user_agents übereinstimmt. Er enthält auch facebook, was mit crawler_user_agents übereinstimmt. Durch das Hinzufügen von MetaIAB – einer für den User-Agent des In-App-Browsers von Facebook einzigartigen Zeichenkette – zu crawler_check_bypass_agents veranlasst dies Discourse, ihm die vollständige Anwendung auszuliefern.


Warum Android und iPad nicht betroffen sind

  • Android: Der In-App-Browser von Facebook auf Android sendet einen anderen User-Agent, der kein facebook enthält, sodass er die Crawler-Erkennung problemlos besteht.
  • iPad: Der In-App-Browser von Facebook auf iPad löst ebenfalls das Crawler-Layout aus, aber da das iPad eine breite window.innerWidth (~1180 px) meldet, liefert Discourse das Desktop-Layout aus, das zufällig ausreichend gerendert wird. Die schmale Ansicht des iPhones (~414 px) löst das Mobile-Layout aus, das im Crawler-Modus vollständig nicht funktionsfähig ist.

Zusätzliche Anmerkung: Flutung durch meta-webindexer

Unabhängig davon sendet der Web-Indexer von Facebook (meta-webindexer/1.1) möglicherweise eine sehr hohe Anzahl von Anfragen an Ihre Seite – potenziell Tausende pro Stunde –, die alle die Startseite zum Ziel haben. Im Gegensatz zu meta-externalagent (das OG-Link-Vorschauen verarbeitet und weiterhin unblockiert bleiben sollte), scheint meta-webindexer für die meisten Discourse-Installationen keinen nützlichen Zweck zu erfüllen.

Wenn Sie diesen Datenverkehr in Ihren Protokollen beobachten, können Sie ihn auf Nginx-Ebene blockieren, indem Sie ihn in Ihre Bot-Block-Konfiguration aufnehmen:

"~*meta-webindexer" 1;

meta-externalagent sollte weiterhin erlaubt bleiben, da es für das Scraping von OG-Metadaten verantwortlich ist, wenn Links auf Facebook geteilt werden.

2 „Gefällt mir“

Danke @shortmort37. Ich habe einen PR erstellt, um die Standardeinstellung im Core so zu ändern, dass MetaIAB enthalten ist:

5 „Gefällt mir“