S3/R2에서 로드된 사용자 정의 이모지는 CDN 라우팅을 우회합니다

개요

S3 또는 Cloudflare R2를 업로드에 사용하고 동시에 커스텀 CDN URL을 설정한 경우, 커스텀 이모지 업로드는 CDN 설정을 무시하고 원본 버킷 URL에서 직접 로드하려 합니다.

문제

관리자가 커스텀 이모지를 업로드하면 업로더가 upload 레코드를 생성하고 데이터베이스에 원본 버킷 URL(예: //my-bucket.s3.amazonaws.com/... 또는 //my-bucket.r2.cloudflarestorage.com/...)을 저장합니다. 이는 표준 Discourse 동작입니다.

그러나 app/models/emoji.rb/site.json을 위한 이모지 캐시를 생성할 때 upload.urlemoji 객체에 직접 전달합니다:

e.url = emoji.upload&.url

CDN 헬퍼를 건너뛰기 때문에 프론트엔드는 원본 버킷 URL을 받게 됩니다. 따라서 버킷의 액세스 정책이 얼마나 엄격한지에 따라 이미지가 깨지거나 Discourse가 이모지를 내부 avatar_proxy를 통해 라우팅하도록 강제됩니다.

해결책

Discourse.store.cdn_url()로 URL 할당을 감싸도록 PR을 열었습니다. 이를 통해 커스텀 이모지 로더가 표준 게시물 이미지와 아바타가 라우팅되는 방식과 일치하도록 합니다.

임시 해결책

PR이 검토되고 병합될 때까지 기다리는 동안, 커스텀 이모지가 DOM에 렌더링되기 직전에 원본 버킷 URL을 올바른 CDN URL로 교체하는 경량 테마 컴포넌트를 만들었습니다(게시물과 채팅 모두에서 작동합니다).

사이트에서 이 버그를 경험하고 있다면, 이 컴포넌트를 설치하고 테마 관리자 설정에서 S3 문자열을 구성하여 깨진 커스텀 이모지를 수정할 수 있습니다:

참고: 이미 업로드한 커스텀 이모지가 현재 깨져 있는 경우, 컨테이너에서 discourse remap "//my-raw-bucket-url.com" "https://my-cdn.com"를 실행하면 데이터베이스의 기존 이모지가 수정되며, 테마 컴포넌트는 PR 수정이 코어에 병합될 때까지 새로 업로드된 이모지를 수정합니다.

5개의 좋아요

기본 이모지 세트 테스트

:smiley:

사용자 지정 이모지 테스트

:falco:

2개의 좋아요

네, 아마도 Cloudflare R2에서만 발생하는 문제인 것 같습니다. 제 인스턴스에서 오류가 발생하고 있고, 새로 업로드된 항목에서만 그런 것 같습니다.

테마 컴포넌트 수정 없이라면, 새 항목을 업로드할 때마다 리맵을 실행해야 합니다. PR이 조금 더 손볼 필요가 있을 것 같은데, 이모지 코딩에는 아주 능숙하지 않아서요.

2개의 좋아요

Discourse는 두 개의 CDN을 사용합니다. 하나는 에셋용이고, 다른 하나는 앱을 프록시하는 용도입니다.

표준 이모지는 하나의 CDN을 사용하고, 사용자 정의 이모지는 다른 CDN을 사용하지만, 올바르게 구성된 두 개의 CDN 설정이 있는 웹사이트에서는 두 경우 모두 CDN으로 보호됩니다.

이 내용에 대해 이 사이트의 첫 번째 관련 주제에서 자세히 설명했습니다.

귀하의 사이트에는 두 개의 CDN이 모두 설정되어 정상적으로 작동하고 있습니까?

4개의 좋아요

아, 한번 확인해 봐야겠네 - 그걸 몰랐어. 고마워!

수정:

클라우드플레어 R2 섹션을 제가 작성했으니, 올바르게 설정되어 있다고 가정해도 될까요? 제가 놓치고 있는 부분이 있을까요?

2개의 좋아요

1개의 좋아요

최근 변경 사항 이후 PR 분지를 설치하고 테스트해 보았는데, 해당 문제가 수정되었음을 확인합니다.

1개의 좋아요

제가 작성한 위키 가이드의 해당 섹션은 다음과 같습니다:

두 값 모두 설정되어 있나요?

이것은 Meta를 AWS에서 Metal로 이동하는 과정에서 발생한 문제입니다. 새로운 쿠키가 누락되어 있었으며, HTML을 다시 빌드하여 수정했습니다.

테스트 사이트에 두 CDN 환경 변수가 모두 설정되어 있나요?

3개의 좋아요

네, 설정은 되어 있습니다. 하지만 제발, DISCOURSE_CDN_URL이 가리키는 CDN 전용 DNS 레코드에 클라우드플레어 설정에서 오타를 내고도 설정할 때 테스트를 안 했으니 사이트가 정상 작동한다고 생각했던 거죠 :laughing: 정말 난장판이었네요.

적어도 그 쓸모없는 PR을 만들면서 이모지 코드 만드는 법에 대해 더 많이 배웠습니다…
:woman_facepalming:t2:

Falco 감사합니다!

4개의 좋아요

하, 걱정 마!

나는 보통 이렇게 가장 많이 배워. 결국 아무것도 남지 않을 거인 토끼굴을 파고드는 거 말이야. 하지만 거기서 얻는 지식은 금값이야!

4개의 좋아요

와, 정말 험난한 여정이었다. 결국 Cloudflare R2 객체 스토리지와 Discourse 인스턴스를 전체적으로 재구성했는데, 이 버그가 R2 관련인 것 같아. Cloudflare DNS 레코드를 수정하고 인스턴스를 재빌드해서 DISCOURSE_CDN_URL이 실제로 해당 주소를 가리키도록 했더니, 번역 문자열 같은 다른 여러 가지가 깨지고 콘솔에 CORS 오류를 포함한 여러 오류가 발생했다. 오늘 하루 종일 엉뚱한 방향으로 빠져들었다. 그래서 DISCOURSE_CDN_URL 사용이 Cloudflare R2와 호환되지 않는 것 같다. (이게 정말 이상했는데, 원래 DNS 항목을 설정할 때 cdn.mysite.com DNS 레코드를 잘못 입력해서 cdn.mysite.com.mysite.com으로 해석되게 되어 있었다.) DISCOURSE_CDN_URL을 올바르게 설정하는 것이 Cloudflare R2 객체 스토리지와 호환되지 않는 것으로 보인다. 여기서 내가 완전히 이해하지 못하는 부분이 더 있을 수도 있다.

어쨌든, 내 PR 브랜치로 재빌드하면 Discourse.store.cdn_url()로 할당을 감싸서 커스텀 이모지 업로드가 표준 게시물 이미지 업로드와 동일한 S3 CDN 라우팅 및 폴백 로직을 따르도록 했기 때문에 모든 것이 정상으로 돌아온다.

PR을 다시 열고 설명을 수정했다. 하지만 Discourse 팀이 이를 병합하지 않기로 결정해도 괜찮다. 왜냐하면 테마 컴포넌트가 클라이언트 레벨에서 문제를 해결해주기 때문이다. 참고로 PR 수정 사항은 커스텀 이모지를 위한 R2 객체 스토리지 설정에만 영향을 미치며, AWS 같은 다른 일반적인 S3 호환 환경에는 영향을 미치지 않는다.

3개의 좋아요

해당 PR이 병합되었으며, 업로드에 Cloudflare R2 객체 스토리지를 사용할 때 커스텀 이모지가 이제 정상적으로 표시됩니다. 관련 R2 문서에 대한 수정 제안은 여기에서 게시했습니다: Configure an S3 compatible object storage provider for uploads

3개의 좋아요

문제가 해결되었습니다. 다시 확인되면 새로운 보고서를 작성해 주세요.