S3/R2から読み込まれたカスタム絵文字はCDNのルーティングをバイパスする

概要

S3 または Cloudflare R2 をアップロード用ストレージとして、かつカスタム CDN URL と併用している場合、カスタム絵文字のアップロードは CDN の設定を無視し、生(raw)のバケット URL から直接読み込もうとします。

問題点

管理者がカスタム絵文字をアップロードすると、アップローダーは upload レコードを作成し、生(raw)のバケット 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 ヘルパーがスキップされるため、フロントエンドには生(raw)のバケット URL が渡されます。その結果、バケットのアクセスポリシーの厳格さによっては、画像が破損したり、Discourse が内部の avatar_proxy を介して絵文字をルーティングせざるを得なくなったりします。

解決策

URL の代入処理を Discourse.store.cdn_url() でラップする PR を作成しました。これにより、カスタム絵文字のローダーが、標準的な投稿画像やアバターと同じようにルーティングされるようになります。

暫定的な回避策

PR のレビューおよびマージを待っている間、カスタム絵文字が DOM にレンダリングされる直前に、生(raw)のバケット URL を適切な CDN URL に置き換える軽量なテーマコンポーネントを作成しました(投稿とチャットの両方で動作します)。

あなたのサイトでこのバグに遭遇している場合は、このコンポーネントをインストールし、テーマ管理設定で S3 の文字列を設定することで、破損しているカスタム絵文字を修復できます:

注意: すでにアップロード済みで現在破損しているカスタム絵文字がある場合、コンテナ内で discourse remap "//my-raw-bucket-url.com" "https://my-cdn.com" を実行すると、データベース内の既存の絵文字が修復されます。一方、テーマコンポーネントは、PR の修正がコアにマージされるまでの間、新しくアップロードされた絵文字の修復を行います。

「いいね!」 3

デフォルトの絵文字のテスト

:smiley:

カスタム絵文字のテスト

:falco:

ああ、もしかしたらCloudflare R2特有の問題かもしれないね。自分のインスタンスで壊れてるよ。新しいものをアップロードしたときだけ壊れるように見える。

テーマコンポーネントの修正がないと、新しいものをアップロードするたびにリマップを実行しなきゃいけないんだ。PRはもう少し作業が必要かも。絵文字のコードにはあまり詳しくないから。

「いいね!」 1

Discourse は 2 つの CDN 構成を使用しており、1 つはアセット用、もう 1 つはアプリのプロキシ用です。

標準絵文字は 1 つの CDN を使用し、カスタム絵文字は別の CDN を使用しますが、適切に設定されたウェブサイトでは、稼働中の 2 CDN 構成によって両方が保護されています。

これは、最初の関連トピックで説明しました。

あなたのサイトには両方の CDN が設定され、稼働していますか?

「いいね!」 2

なるほど、確認してみないといけないですね。知りませんでした。ありがとうございます!

編集:

Cloudflare R2のセクションを書いた私なので、設定は正しいと仮定してよいでしょうか? 何が不足しているのでしょうか?

ここでの確認ですが、最近の変更後にPRブランチをインストールしてテストし、この問題が修正されていることを確認しました。