Cloudflare R2 Bild-URL Anzeigeproblem: Detaillierte Erklärung und Lösung

Problembeschreibung

Wir haben kürzlich ein Problem mit der Bildanzeige im Forum festgestellt, insbesondere:

  • Bild-Thumbnails werden nicht korrekt angezeigt.
  • Beim Klicken auf die Bilder wird das Vollbildbild korrekt angezeigt.
  • Die Entwicklertools des Browsers zeigen falsche Bild-URLs an.

Nach der Untersuchung ist die Ursache ein falscher Domainname in den Bild-URLs:

  • Korrekte URL: https://store.starorigin.cc/optimized/1X/[imageID].jpeg
  • Falsche URL: https://info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com/optimized/1X/[imageID].jpeg

Das System verwendet die falsche Domain des R2-Buckets anstelle unserer konfigurierten CDN-Domain.

Technische Analyse

Dies ist ein bekanntes Problem mit Discourse bei der Verarbeitung von Bildern, die in Cloudflare R2 gespeichert sind. In einigen Fällen kann Discourse, selbst wenn s3_cdn_url konfiguriert ist, beim Generieren optimierter Bilder (wie Thumbnails) immer noch die rohe Speicher-URL anstelle der CDN-URL verwenden.

Dies könnte mit folgenden Faktoren zusammenhängen:

  • Discourse-Version
  • Die Konfiguration des S3-kompatiblen Speichers
  • Wie URLs in der OptimizedImage-Tabelle gespeichert werden

Lösung

Die einfachste und effektivste Lösung ist die Verwendung einer Discourse-Themenkomponente zur clientseitigen Reparatur. Dies erfordert keine Datenbankoperationen oder Änderungen an der Serverkonfiguration. Es beinhaltet lediglich das Hinzufügen eines kurzen JavaScript-Code-Snippets, das die falschen URLs im Browser automatisch durch die richtigen ersetzt.

Code der Themenkomponente

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer("0.11.1", (api) => {
  // Bereits geladene Bilder reparieren
  function fixImageUrls() {
    const badDomain = "info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com";
    const goodDomain = "store.starorigin.cc";

    // Normale Bilder reparieren
    document.querySelectorAll(`img[src*="${badDomain}"]`).forEach(img => {
      img.src = img.src.replace(badDomain, goodDomain);
    });

    // Lazy-loaded Bilder reparieren
    document.querySelectorAll(`img[data-src*="${badDomain}"]`).forEach(img => {
      img.setAttribute('data-src', img.getAttribute('data-src').replace(badDomain, goodDomain));
    });

    // Hintergrundbilder reparieren
    document.querySelectorAll('[style*="background"]').forEach(el => {
      if (el.style.backgroundImage && el.style.backgroundImage.includes(badDomain)) {
        el.style.backgroundImage = el.style.backgroundImage.replace(badDomain, goodDomain);
      }
    });

    // Verschiedene andere potenzielle Attribute reparieren
    ['srcset', 'data-large-src', 'data-small-src', 'data-download-href'].forEach(attr => {
      document.querySelectorAll(`[${attr}*="${badDomain}"]`).forEach(el => {
        el.setAttribute(attr, el.getAttribute(attr).replace(badDomain, goodDomain));
      });
    });
  }

  // Bilder im Editor reparieren
  api.decorateCooked($elem => {
    fixImageUrls();
  }, { id: 'fix-r2-image-urls' });

  // Nach dem initialen Laden reparieren
  api.onPageChange(() => {
    fixImageUrls();
  });

  // Dynamisch geladene Inhalte behandeln
  const observer = new MutationObserver(mutations => {
    fixImageUrls();
  });

  // Beobachtung starten, nachdem das DOM geladen ist
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', () => {
      fixImageUrls();
      startObserver();
    });
  } else {
    fixImageUrls();
    startObserver();
  }

  function startObserver() {
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['src', 'data-src', 'srcset', 'style']
    });
  }
});

Funktionsweise des Codes

Dieser Code führt folgende Aktionen aus:

  1. Umfassende Erkennung: Findet alle Bild-URLs, die die falsche Domain enthalten.
  2. Behandlung mehrerer Elemente: Behandelt verschiedene Bildelemente und Attribute (img-Tags, lazy-loaded Bilder, Hintergrundbilder usw.).
  3. Dynamische Überwachung: Verwendet einen MutationObserver, um Seitenänderungen zu überwachen und sicherzustellen, dass auch dynamisch geladene Inhalte repariert werden.
  4. Discourse-Integration: Integriert sich in die Discourse-API, um verschiedene Sonderszenarien zu behandeln.

Installationsschritte

  1. Melden Sie sich bei Ihrem Discourse-Administratorkonto an.
  2. Gehen Sie zu Admin > Anpassen > Themenkomponenten.
  3. Klicken Sie auf die Schaltfläche Neu.
  4. Wählen Sie die Option Neue Komponente erstellen.
  5. Benennen Sie sie „Fix R2 Image URLs“ (oder einen beliebigen Namen Ihrer Wahl).
  6. Fügen Sie im Tab „Javascript“ den obigen Code ein.
  7. Klicken Sie auf die Schaltfläche Erstellen.
  8. Klicken Sie auf die Schaltfläche Aktivieren und wählen Sie das Thema aus, auf das Sie sie anwenden möchten (normalerweise „Standard“).

Überprüfung

Nach der Installation:

  1. Aktualisieren Sie die Forumseite.
  2. Zeigen Sie Beiträge mit Bildern an.
  3. Bestätigen Sie, dass die Thumbnails korrekt angezeigt werden.
  4. Verwenden Sie die Entwicklertools Ihres Browsers, um zu überprüfen, ob alle Bildanfragen auf die CDN-Domain verweisen.

Obwohl eine clientseitige Lösung der einfachste, schnellste und risikoärmste Ansatz ist, insbesondere wenn der direkte Serverzugriff begrenzt ist.

Fazit

Diese einfache Themenkomponente behebt effektiv das Problem mit den Bild-URLs bei der Integration von Discourse mit Cloudflare R2-Speicher, ohne dass Serveränderungen oder komplexe Konfigurationen erforderlich sind. Obwohl sie das Problem clientseitig behebt und nicht die eigentliche Ursache angeht, ist sie einfach zu implementieren, liefert sofortige Ergebnisse und ist eine ideale Lösung.

Wenn Ihre Discourse-Site ebenfalls ähnliche Probleme hat, können Sie diese Lösung gerne ausprobieren.

4 „Gefällt mir“

betrifft dieses Problem nur den Chat? Ich versuche, den Umfang zu verstehen.

Vielen Dank für Ihren sehr hilfreichen Bericht hier!

1 „Gefällt mir“

Ja, dieser Fehler betrifft nur den Chat. Mein S3-Dienstanbieter ist Cloudflare R2. Wenn ich ein Bild in der Chat-Oberfläche sende, kann das Bild nicht die Standard-CDN-Link-Einstellungen verwenden, was zum Fehlschlagen des Bildladens führt.

1 „Gefällt mir“

Scheint immer noch der Fall zu sein, wie in Upload images in chat can't be show normally when use s3 CDN, und ein Fix wurde versucht, aber später rückgängig gemacht.