0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-04 10:39:43 +08:00
discourse/app/serializers/emoji_serializer.rb
Lilly cc1123ea42
FIX: Apply CDN to Custom Emojis loaded from S3/R2 (#41267)
When a Discourse instance is configured to use S3 (or S3-compatible
storage like Cloudflare R2) for uploads, the Custom Emoji uploader saves
the raw bucket URL to the `uploads` table (e.g.,
`//my-bucket.s3.amazonaws.com/...`).

Currently, when the Emoji cache is generated for `/site.json`,
`app/models/emoji.rb` passes `emoji.upload&.url` directly. If a
dedicated App CDN (`DISCOURSE_CDN_URL`) is not configured, this causes
newly uploaded Custom Emojis to completely bypass the configured
`DISCOURSE_S3_CDN_URL` and attempt to load directly from the raw bucket
URL, resulting in broken images.

Additionally, during live uploads via the Admin UI, the API response
returns a broken relative path, resulting in a broken image preview
until the page is forcibly refreshed.

**Why `DISCOURSE_CDN_URL` is intentionally omitted in this
architecture:**
While the standard advice is to configure an App CDN, this is physically
impossible for admins who proxy their main domain through Cloudflare to
handle their app caching.
If an admin attempts to define a secondary `DISCOURSE_CDN_URL` (e.g.,
`cdn.forum.com`) using a standard Cloudflare DNS record, Cloudflare
cannot rewrite the `Host` header to match the origin domain (to prevent
Domain Fronting). Because the `Host` header doesn't match
`DISCOURSE_HOSTNAME`, Discourse's internal NGINX server rejects the CDN
requests with a `301 Redirect`, instantly triggering CORS errors and
breaking the site's Javascript.

Therefore, admins using the Cloudflare Proxy + S3/R2 architecture *must*
leave `DISCOURSE_CDN_URL` blank while setting `DISCOURSE_S3_CDN_URL`.

**The Solution:**
This PR wraps the assignment in `Discourse.store.cdn_url()` so that
Custom Emoji uploads obey the same S3 CDN routing and fallback logic as
standard post image uploads. This ensures the emojis route to the S3 CDN
successfully, and fixes the broken API response generation during live
uploads at the backend level.

**Files touched:**
* `app/models/emoji.rb`
* `spec/models/emoji_spec.rb`

---------

Co-authored-by: Lilly <lilly@discourse.org>
Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
2026-07-01 17:05:28 -04:00

13 lines
209 B
Ruby
Vendored

# frozen_string_literal: true
class EmojiSerializer < ApplicationSerializer
attributes :name, :url, :group, :created_by
def created_by
object.created_by
end
def url
object.cdn_url
end
end