Ao usar S3 ou Cloudflare R2 para uploads junto com uma URL de CDN personalizada, os uploads de emojis personalizados não respeitam a configuração do CDN e tentam carregar diretamente da URL bruta do bucket.
O problema
Quando um administrador faz upload de um emoji personalizado, o uploader cria um registro upload e salva a URL bruta do bucket no banco de dados (por exemplo, //my-bucket.s3.amazonaws.com/... ou //my-bucket.r2.cloudflarestorage.com/...) — este é o comportamento padrão do Discourse.
No entanto, quando app/models/emoji.rb gera o cache de emojis para /site.json, ele passa a upload.url diretamente para o objeto emoji:
e.url = emoji.upload&.url
Por pular o helper do CDN, o frontend recebe a URL bruta do bucket. Assim, dependendo de quão restritivas são as políticas de acesso do bucket, isso resulta em imagens quebradas ou força o Discourse a rotear os emojis através do avatar_proxy interno.
Solução
Abri um PR que envolve as atribuições de URL no Discourse.store.cdn_url(), o que faz com que o carregador de emojis personalizados esteja alinhado com a forma como as imagens de postagens padrão e os avatares são roteados.
Solução temporária
Enquanto aguardamos que o PR seja revisado e mesclado, criei um componente de tema leve que substitui a URL bruta do bucket pela URL correta do CDN logo antes que o emoji personalizado seja renderizado no DOM (funciona tanto para postagens quanto para chat).
Se você estiver enfrentando este bug no seu site, pode instalar este componente e configurar suas strings do S3 nas configurações do administrador do tema para corrigir qualquer emoji personalizado quebrado:
Nota: se você já fez upload de emojis personalizados que estão atualmente quebrados, executar discourse remap "//my-raw-bucket-url.com" "https://my-cdn.com" no container corrigirá os antigos no banco de dados, enquanto o componente de tema corrigirá qualquer um recém-upload até que a correção do PR seja mesclada no núcleo.
Pode ser que seja algo exclusivo do Cloudflare R2, então. Está falhando na minha instância. Parece que só falha com os novos que são enviados.
Sem a correção do componente do tema, tenho que executar o remapeamento toda vez que envio um novo. O PR pode precisar de alguns ajustes — não sou muito bom com o código dos emojis.
O Discourse utiliza uma configuração com dois CDNs: um para ativos (assets) e outro atuando como proxy para a aplicação.
Os emojis padrão usam um CDN, enquanto os emojis personalizados usam o outro, mas ambos ficam protegidos por um CDN em um site corretamente configurado com essa configuração de dois CDNs.
Já detalhei isso no primeiro tópico relacionado aqui:
Seu site tem ambos os CDNs configurados e funcionando?
Eu as tenho definidas, mas, por amor de Deus, eu tinha um erro de digitação na minha configuração do Cloudflare para o registro DNS específico do CDN que DISCOURSE_CDN_URL aponta, e eu nunca testei quando configurei porque meu site estava funcionando que confusão total.
Pelo menos aprendi mais sobre criação de código de emoji fazendo aquele PR inútil…
nossa, que jornada essa foi. basicamente reconfigurei toda minha instância do Cloudfare R2 e do Discourse, e acho que esse bug é legítimo para o R2. quando corrigi meu registro de DNS do Cloudflare e reconstruí a instância para que DISCOURSE_CDN_URL realmente apontasse para ele, estragou um monte de outras coisas, como strings de tradução, e gerou vários erros no console, incluindo alguns erros de CORS. isso me levou por muitos caminhos equivocados hoje. então acho que usar DISCOURSE_CDN_URL parece ser incompatível com o Cloudflare R2. (isso foi muito estranho — quando configurei originalmente minha entrada de DNS, inseri incorretamente o registro de DNS cdn.mysite.com de forma que estava resolvendo como cdn.mysite.com.mysite.com). definir DISCOURSE_CDN_URL corretamente parece ser incompatível com o armazenamento de objetos do Cloudflare R2. pode haver outras coisas aqui que eu não estou entendendo completamente.
enfim, quando reconstruí com minha branch de PR, tudo foi corrigido porque envolve a atribuição em Discourse.store.cdn_url(), para que os uploads de emojis personalizados sigam a mesma lógica de roteamento e fallback do CDN S3 que os uploads de imagens padrão de posts.
reabri o PR e editei a descrição. mas acho que se a equipe do Discourse escolher não mesclar, tudo bem, porque o componente de tema corrige o problema no nível do cliente. observe que a correção do PR deve afetar apenas as configurações de armazenamento de objetos R2 para emojis personalizados e não outros serviços compatíveis com S3 como a AWS.
Este PR foi mesclado e os emojis personalizados agora estão corrigidos ao usar o armazenamento de objetos Cloudflare R2 para uploads. Postei uma sugestão de atualização para a documentação relevante do R2 aqui: Configure an S3 compatible object storage provider for uploads