Problema di visualizzazione URL immagine Cloudflare R2: spiegazione dettagliata e soluzione

Descrizione del problema

Recentemente abbiamo riscontrato un problema con la visualizzazione delle immagini sul forum, in particolare:

  • Le miniature delle immagini non vengono visualizzate correttamente.
  • Facendo clic sulle immagini, viene visualizzata correttamente l’immagine a grandezza naturale.
  • Gli strumenti per sviluppatori del browser mostrano URL delle immagini errati.

Dopo l’indagine, la causa principale è un nome di dominio errato negli URL delle immagini:

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

Il sistema sta utilizzando il dominio errato del bucket R2 grezzo invece del nostro dominio CDN configurato.

Analisi tecnica

Questo è un problema noto con Discourse quando gestisce immagini archiviate in Cloudflare R2. In alcuni casi, anche quando s3_cdn_url è configurato, Discourse potrebbe comunque utilizzare l’URL di archiviazione grezzo anziché l’URL CDN quando genera immagini ottimizzate (come le miniature).

Ciò potrebbe essere correlato ai seguenti fattori:

  • Versione di Discourse
  • La configurazione dello storage compatibile con S3
  • Come gli URL sono archiviati nella tabella OptimizedImage

Soluzione

La soluzione più semplice ed efficace è utilizzare un componente tema di Discourse per la riparazione lato client. Ciò non richiede operazioni sul database o modifiche alla configurazione del server. Coinvolge solo l’aggiunta di un breve snippet di codice JavaScript che sostituisce automaticamente gli URL errati con quelli corretti nel browser.

Codice del componente tema

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

export default apiInitializer("0.11.1", (api) => {
  // Correggi le immagini già caricate
  function fixImageUrls() {
    const badDomain = "info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com";
    const goodDomain = "store.starorigin.cc";

    // Correggi le immagini normali
    document.querySelectorAll(`img[src*="${badDomain}"]`).forEach(img => {
      img.src = img.src.replace(badDomain, goodDomain);
    });

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

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

    // Correggi vari altri attributi potenziali
    ['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));
      });
    });
  }

  // Correggi le immagini nell'editor
  api.decorateCooked($elem => {
    fixImageUrls();
  }, { id: 'fix-r2-image-urls' });

  // Correggi dopo il caricamento iniziale
  api.onPageChange(() => {
    fixImageUrls();
  });

  // Gestisci contenuti caricati dinamicamente
  const observer = new MutationObserver(mutations => {
    fixImageUrls();
  });

  // Inizia l'osservazione dopo il caricamento del DOM
  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']
    });
  }
});

Come funziona il codice

Questo codice esegue le seguenti azioni:

  1. Rilevamento completo: Trova tutti gli URL delle immagini contenenti il dominio errato.
  2. Gestione di elementi multipli: Gestisce vari elementi e attributi di immagine (tag img, immagini lazy-loaded, immagini di sfondo, ecc.).
  3. Monitoraggio dinamico: Utilizza un MutationObserver per monitorare le modifiche della pagina, garantendo che anche i contenuti caricati dinamicamente vengano corretti.
  4. Integrazione con Discourse: Si integra con l’API di Discourse per gestire vari scenari speciali.

Passaggi di installazione

  1. Accedi al tuo account amministratore di Discourse.
  2. Vai su Admin > Personalizza > Componenti tema.
  3. Fai clic sul pulsante Nuovo.
  4. Seleziona l’opzione Crea nuovo componente.
  5. Chiamalo “Fix R2 Image URLs” (o qualsiasi nome preferisci).
  6. Nella scheda “Javascript”, incolla il codice sopra.
  7. Fai clic sul pulsante Crea.
  8. Fai clic sul pulsante Abilita e scegli il tema a cui applicarlo (solitamente “Predefinito”).

Verifica

Dopo l’installazione:

  1. Aggiorna la pagina del forum.
  2. Visualizza i post contenenti immagini.
  3. Conferma che le miniature vengano visualizzate correttamente.
  4. Utilizza gli strumenti per sviluppatori del tuo browser per verificare che tutte le richieste di immagini puntino al dominio CDN.

Sebbene una soluzione lato client sia l’approccio più semplice, veloce e a minor rischio, specialmente quando l’accesso diretto al server è limitato.

Conclusione

Questo semplice componente tema risolve efficacemente il problema degli URL delle immagini durante l’integrazione di Discourse con lo storage Cloudflare R2, senza richiedere modifiche al server o configurazioni complesse. Sebbene risolva il problema lato client anziché affrontare la causa principale, è facile da implementare, fornisce risultati immediati ed è una soluzione ideale.

Se anche il tuo sito Discourse sta riscontrando problemi simili, sentiti libero di provare questa soluzione.

4 Mi Piace

questo problema influisce solo sulla chat? sto cercando di capire l’ambito.

Grazie per il tuo utilissimo resoconto qui!

1 Mi Piace

Sì, questo bug influisce solo sulla chat. Il mio provider di servizi S3 è Cloudflare R2. Quando invio un’immagine nell’interfaccia di chat, l’immagine non può utilizzare le impostazioni predefinite del link CDN, con conseguente impossibilità di caricare l’immagine.

1 Mi Piace

Sembra essere ancora il caso di Upload images in chat can't be show normally when use s3 CDN, e un fix è stato tentato ma poi annullato