Chat-Vorschaubilder umgehen s3_cdn_url und verwenden direkte S3-Bucket-URLs

Ich habe kürzlich eine Cloudflare R2-Upload-Bucket-Konfiguration vorgenommen, und meine Chat-Vorschaubilder waren defekt. Also habe ich etwas recherchiert, eine schnelle Korrektur für meine Konfiguration vorgenommen und dabei dieses Thema gefunden: Cloudflare R2 Image URL Display Issue: Detailed Explanation and Fix. Wie auch immer, ich habe mir andere S3-Upload-Bucket-Konfigurationen angesehen und festgestellt, dass es sich bei dem Fehler nicht wirklich um ein Cloudflare-spezifisches Problem handelt.


Beschreibung

Wenn ein externer S3- oder kompatibler Objektspeicher für Uploads konfiguriert ist, umgehen Chat-Vorschaubilder das CDN und werden direkt von der Bucket-URL geladen.

Bei sicheren externen S3-kompatiblen Buckets wie Cloudflare R2 sind Chat-Vorschaubilder defekt und werden nicht angezeigt.

Das zugrundeliegende Problem besteht darin, dass der Chat-Serializer die Einstellung s3_cdn_url nicht auf Vorschaubilder anwendet. Anstatt das Bild über das konfigurierte CDN zu leiten, wird die rohe interne S3-Bucket-URL direkt in die Browser-Payloads geleckt.

Schritte zur Reproduktion

Dies ist auf Meta und anderen Sites, die S3-Upload-Buckets verwenden, reproduzierbar:

  1. Lade ein Bild im Chat oder in einem Kanal hoch.
  2. Untersuche die URL des Vorschaubilds in der Konsole.
  3. Klicke auf das Bild, um die größere Originalversion zu erhalten, und untersuche die URL.
  4. Vergleiche sie mit der des Vorschaubilds.

Hier ist ein Beispiel aus einem Meta-Chat:

Vorschaubild-URL: direkt vom Bucket

https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/meta/optimized/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532_2_375x500.jpeg

Original-URL: über das CDN

https://global.discourse-cdn.com/meta/original/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532.jpeg

In der Konsole enthält das HTML des Vorschaubilds <img... das Attribut data-large-src mit der CloudFront-CDN-URL und src mit der AWS-Bucket-URL.

Screenshot

Auswirkungen:

  • Bei S3-kompatiblen Speichern wie Cloudflare R2, die standardmäßig sicher sind und nicht-authentifizierten Zugriff auf rohe Bucket-Endpunkte blockieren, sind Chat-Vorschaubilder (optimiert) defekt.
  • Bandlecks für AWS und andere S3-kompatible Objektspeicher-Buckets, die Zugriff auf rohe Bucket-Endpunkte erlauben, da der Chat das CDN vollständig umgeht; dies führt dazu, dass direkte S3-Egress-Gebühren für gesamten Chat-Vorschaubild-Datenverkehr anfallen.
  • Infrastruktur-Lecks: Die rohen Backend-Speicher-URLs (einschließlich interner Bucket-Namen und manchmal Konten-IDs) werden in den Client-JSON-Payloads offengelegt.

Pull Request:

Ich habe einen PR zur Behebung des Problems hier eingereicht:

https://github.com/discourse/discourse/pull/40419

Es sieht so aus, als hätte Sam getURLWithCDN zum Chat-Composer-Vorschau hinzugefügt – jedoch scheint es, dass dies nicht in den Chat-Stream gelangt?

Ich frage mich, ob die Composer-Korrektur für einige S3-Konfigurationen ebenfalls fehlgeschlagen sein könnte, da getURLWithCDN bei Protokollmismatches (// vs. https://) abstürzt? Jedenfalls erweitert der oben genannte PR einfach Sams Arbeit, indem er Wrapper für den Stream hinzufügt und ihn protokollunabhängig macht.

Temporäre Workaround:

Bevor mir klar wurde, dass dies mehr als nur ein Cloudflare-Problem war, habe ich eine leichte Theme-Komponente erstellt. Sie fängt die rohen S3-Domains im Chat-DOM ab und tauscht sie vor dem Download durch den Browser gegen die korrekte CDN-Domain aus. Dies leitet den Datenverkehr korrekt um und schließt das Bandbreiten-Leck. Ich habe sie so angepasst, dass sie für jeden S3-kompatiblen Objektspeicher funktioniert. Es werden nur zwei Einstellungen benötigt: Raw S3 bucket URL und S3 CDN URL.

https://github.com/Lillinator/chat-s3-thumbnails-fix

(keine Ahnung, warum die GitHub-Oneboxen hier defekt sind) jetzt behoben

5 „Gefällt mir“

Wahrscheinlich im Zusammenhang mit dem Umzug der Seite… Ich habe es gerade neu gebacken.

2 „Gefällt mir“

Hallo, wurde der PR bereits gemergt?

Danke

2 „Gefällt mir“

Es wartet nur noch auf die Prüfung durch ein menschliches Teammitglied, nachdem mein Kollege discourse-triage-bot einige Tests behoben hat :slight_smile:

https://github.com/discourse/discourse/pull/40419#issuecomment-4683409099

5 „Gefällt mir“

Sieht so aus, als wäre es jetzt gemergt.

4 „Gefällt mir“

auf Wunsch des Autors geöffnet

Für Foren mit benutzerdefinierten Emojis, die hinzugefügt wurden, sind diese im Chat jetzt defekt, da die Korrektur zusammengeführt wurde.

Im Gegensatz zu Standard-Beitragsbildern (die mit rake posts:rebake repariert werden können), werden benutzerdefinierte Chat-Emojis dynamisch über /site.json an das Frontend übergeben.

Wenn Ihre Datenbank S3-URLs enthält, die das Protokoll fehlen (z. B. //bucket.endpoint...) oder eine virtual-hosted Style-Domain verwenden, die nicht perfekt mit Ihren app.yml-Umgebungsvariablen übereinstimmt, schlägt der interne CDN-Ersetzer von Discourse stillschweigend fehl. Die rohe Bucket-URL wird an den Browser übergeben, wodurch die benutzerdefinierten Emojis im Chat defekt werden.

So beheben Sie das Problem:

Um dies dauerhaft zu beheben, müssen Sie die rohen Bucket-URLs gewaltsam auf Ihre CDN-URL in der Datenbank ummappen und dann den Site-Cache leeren, damit /site.json neu generiert wird.

1. Geben Sie Ihren Container ein:

Melden Sie sich per SSH auf Ihrem Server an und betreten Sie Ihren Discourse-Container (normalerweise app oder web_only, wenn Sie ein Zwei-Container-Setup haben).

cd /var/discourse
./launcher enter app

2. Mappen Sie die URLs um:

Führen Sie das integrierte Discourse-Tool remap aus. Sie sollten es zweimal ausführen, um sowohl die https://-Variante als auch die schemaless //-Variante zu erfassen, die das Migrations-Skript manchmal zurücklässt.

Ersetzen Sie die Platzhalter durch Ihre tatsächliche rohe Bucket-URL und Ihre tatsächliche CDN-URL:

# Reparieren Sie die Standard-https:// URLs
discourse remap "https://<Ihre-Bucket>.<Ihr-Endpoint>.com" "https://cdn.your-domain.com"

# Reparieren Sie die schemaless // URLs (das ist die, die normalerweise die benutzerdefinierten Emojis defekt macht)
discourse remap "//<Ihre-Bucket>.<Ihr-Endpoint>.com" "https://cdn.your-domain.com"

3. Leeren Sie den Cache

Da /site.json stark zwischengespeichert wird, müssen Sie den Rails-Cache leeren, um das Forum dazu zu zwingen, die neuen URLs auszuliefern:

Öffnen Sie die Rails-Konsole:

rails c

Führen Sie diese Befehle aus:

Rails.cache.clear
Site.clear_cache
exit

4. Aktualisieren Sie

Führen Sie einen harten Browser-Refresh durch (und deaktivieren Sie die Theme-Component-Workaround, falls Sie diesen noch verwenden). Die benutzerdefinierten Emojis im Chat sollten jetzt behoben sein und korrekt über das CDN geladen werden.

3 „Gefällt mir“

Hey Lilly, vielen Dank für deine tolle Arbeit. Nach den beiden Remaps funktionieren jetzt meine alten Uploads und Thumbnails wie erwartet. Vorher funktionierten sogar die Bilder unter “/admin/config/customize/themes” nicht. Jetzt ist alles behoben. Das ist super.

Danke

1 „Gefällt mir“