Обзор
При использовании S3 или Cloudflare R2 для загрузки файлов вместе с пользовательским URL-адресом CDN, загрузка пользовательских эмодзи не учитывает конфигурацию CDN и пытается загружаться напрямую с URL-адреса исходного хранилища (бакета).
Суть проблемы
Когда администратор загружает пользовательский эмодзи, система загрузки создает запись upload и сохраняет в базе данных сырой URL-адрес хранилища (например, //my-bucket.s3.amazonaws.com/... или //my-bucket.r2.cloudflarestorage.com/...) — это стандартное поведение Discourse.
Однако, когда app/models/emoji.rb формирует кэш эмодзи для /site.json, он передает upload.url напрямую в объект emoji:
e.url = emoji.upload&.url
Поскольку помощник для CDN (CDN helper) игнорируется, фронтенд получает сырой URL-адрес хранилища. В зависимости от строгости политик доступа к хранилищу это приводит к неработающим изображениям или вынуждает Discourse проксировать эмодзи через внутренний avatar_proxy.
Решение
Я создал PR, который оборачивает присваивание URL-адресов в Discourse.store.cdn_url(), что позволяет загрузчику пользовательских эмодзи работать так же, как и стандартные изображения в постах и аватары.
Временное решение
Пока ожидается рассмотрение и слияние PR, я создал легковесный компонент темы, который заменяет сырой URL-адрес хранилища на правильный URL-адрес CDN непосредственно перед рендерингом пользовательского эмодзи в DOM (работает как для постов, так и для чата).
Если на вашем сайте наблюдается эта ошибка, вы можете установить этот компонент и настроить строки S3 в настройках администратора темы, чтобы исправить неработающие пользовательские эмодзи:
Примечание: если вы уже загрузили пользовательские эмодзи, которые сейчас не отображаются, выполнение команды discourse remap "//my-raw-bucket-url.com" "https://my-cdn.com" в контейнере исправит старые записи в базе данных, а компонент темы исправит все новые загруженные эмодзи до тех пор, пока исправление не будет включено в ядро Discourse.
