Descrição do Problema
Recentemente, notamos um problema com a exibição de imagens no fórum, especificamente:
- As miniaturas das imagens não estão sendo exibidas corretamente.
- Clicar nas imagens exibe a imagem em tamanho real corretamente.
- As ferramentas de desenvolvedor do navegador mostram URLs de imagem incorretas.
Após investigação, a causa raiz é um nome de domínio incorreto nas URLs das imagens:
- URL Correta:
https://store.starorigin.cc/optimized/1X/[imageID].jpeg - URL Incorreta:
https://info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com/optimized/1X/[imageID].jpeg
O sistema está usando o domínio incorreto do bucket R2 bruto em vez do nosso domínio CDN configurado.
Análise Técnica
Este é um problema conhecido com o Discourse ao lidar com imagens armazenadas no Cloudflare R2. Em alguns casos, mesmo quando s3_cdn_url está configurado, o Discourse pode ainda usar o URL de armazenamento bruto em vez do URL do CDN ao gerar imagens otimizadas (como miniaturas).
Isso pode estar relacionado aos seguintes fatores:
- Versão do Discourse
- A configuração do armazenamento compatível com S3
- Como os URLs são armazenados na tabela
OptimizedImage
Solução
A solução mais simples e eficaz é usar um componente de tema do Discourse para reparo no lado do cliente. Isso não requer nenhuma operação de banco de dados ou alterações na configuração do servidor. Envolve apenas a adição de um pequeno trecho de código JavaScript que substitui automaticamente os URLs incorretos pelos corretos no navegador.
Código do Componente de Tema
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer("0.11.1", (api) => {
// Corrige imagens já carregadas
function fixImageUrls() {
const badDomain = "info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com";
const goodDomain = "store.starorigin.cc";
// Corrige imagens regulares
document.querySelectorAll(`img[src*="${badDomain}"]`).forEach(img => {
img.src = img.src.replace(badDomain, goodDomain);
});
// Corrige imagens com carregamento lento (lazy-loaded)
document.querySelectorAll(`img[data-src*="${badDomain}"]`).forEach(img => {
img.setAttribute('data-src', img.getAttribute('data-src').replace(badDomain, goodDomain));
});
// Corrige imagens de fundo
document.querySelectorAll('[style*="background"]').forEach(el => {
if (el.style.backgroundImage && el.style.backgroundImage.includes(badDomain)) {
el.style.backgroundImage = el.style.backgroundImage.replace(badDomain, goodDomain);
}
});
// Corrige vários outros atributos potenciais
['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));
});
});
}
// Corrige imagens no editor
api.decorateCooked($elem => {
fixImageUrls();
}, { id: 'fix-r2-image-urls' });
// Corrige após o carregamento inicial
api.onPageChange(() => {
fixImageUrls();
});
// Lida com conteúdo carregado dinamicamente
const observer = new MutationObserver(mutations => {
fixImageUrls();
});
// Começa a observar após o DOM ser carregado
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']
});
}
});
Como o Código Funciona
Este código realiza as seguintes ações:
- Detecção Abrangente: Encontra todos os URLs de imagem que contêm o domínio incorreto.
- Manuseio de Múltiplos Elementos: Lida com vários elementos e atributos de imagem (tags img, imagens com carregamento lento, imagens de fundo, etc.).
- Monitoramento Dinâmico: Usa um
MutationObserverpara monitorar as alterações na página, garantindo que o conteúdo carregado dinamicamente também seja corrigido. - Integração com Discourse: Integra-se com a API do Discourse para lidar com vários cenários especiais.
Passos de Instalação
- Faça login na sua conta de administrador do Discourse.
- Vá para Admin > Personalizar > Componentes de Tema.
- Clique no botão Novo.
- Selecione a opção Criar novo componente.
- Nomeie-o como “Fix R2 Image URLs” (ou qualquer nome que preferir).
- Na aba “Javascript”, cole o código acima.
- Clique no botão Criar.
- Clique no botão Ativar e escolha o tema ao qual aplicá-lo (geralmente “Padrão”).
Verificação
Após a instalação:
- Recarregue a página do fórum.
- Visualize postagens que contenham imagens.
- Confirme que as miniaturas estão sendo exibidas corretamente.
- Use as ferramentas de desenvolvedor do seu navegador para verificar se todas as requisições de imagem estão apontando para o domínio CDN.
Embora uma solução do lado do cliente seja a abordagem mais simples, rápida e de menor risco, especialmente quando o acesso direto ao servidor é limitado.
Conclusão
Este componente de tema simples aborda efetivamente o problema do URL da imagem ao integrar o Discourse com o armazenamento Cloudflare R2, sem a necessidade de alterações no servidor ou configurações complexas. Embora corrija o problema no lado do cliente em vez de abordar a causa raiz, é fácil de implementar, fornece resultados imediatos e é uma solução ideal.
Se o seu site Discourse também estiver enfrentando problemas semelhantes, sinta-se à vontade para experimentar esta solução.
