تجاوز صور مصغرة للدردشة لـ s3_cdn_url واستخدام عناوين S3 bucket الخام

أجريت مؤخرًا إعدادًا لحفظة رفع Cloudflare R2، فظهرت مشكلات في صور المصغرات للدردشة. لذا قمت ببعض البحث وأصلحت الإعداد بسرعة، ثم عثرت على هذا الموضوع: Cloudflare R2 Image URL Display Issue: Detailed Explanation and Fix. على أي حال، تفحصت إعدادات حفظة رفع S3 الأخرى ولاحظت أن المشكلة ليست محددة بـ Cloudflare حقًا.


الوصف

عند إعداد مخزن كائنات خارجي متوافق مع S3 للرفع، تتجاوز صور المصغرات في الدردشة شبكة توصيل المحتوى (CDN) وتُحمَّل مباشرةً من عنوان URL الخاص بالحافظة.

في حالة الحفظة الآمنة المتوافقة مع S3 مثل Cloudflare R2، لا تظهر صور المصغرات في الدردشة وتكون معطلة.

السبب الجذري هو أن مُسلسل الدردشة يفشل في تطبيق إعداد s3_cdn_url على المصغرات. فبدلًا من توجيه الصورة عبر شبكة توصيل المحتوى المهيأة، يتم تسريب عنوان URL الداخلي الخام للحافظة مباشرةً إلى حمولات المتصفح.

خطوات التكرار

يمكن تكرار هذه المشكلة في Meta ومواقع أخرى تستخدم حفظة رفع S3:

  1. انشر صورة في دردشة أو قناة.
  2. افحص عنوان URL لصورة المصغرة في وحدة التحكم (Console).
  3. انقر على الصورة للحصول على النسخة الأصلية الأكبر حجمًا، ثم افحص عنوان URL الخاص بها.
  4. قارن بينه وبين عنوان URL للمصغرة.

إليك مثال من دردشة Meta:

عنوان URL للمصغرة: من الحافظة

https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/meta/optimized/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532_2_375x500.jpeg

عنوان URL الأصلي: عبر شبكة توصيل المحتوى

https://global.discourse-cdn.com/meta/original/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532.jpeg

في وحدة التحكم، يحتوي عنصر HTML الخاص بالمصغرة <img... على data-large-src = عنوان URL الخاص بشبكة CloudFront CDN، بينما يحتوي src على عنوان URL الخاص بحافظة AWS.

لقطة شاشة

الأثر:

  • بالنسبة لتخزين متوافق مع S3 مثل Cloudflare R2 الذي يكون آمنًا افتراضيًا ويمنع الوصول غير المصادق عليه إلى نقاط نهاية الحافظة الخام، فإن صور المصغرات في الدردشة (المحسنة) تكون معطلة.
  • تسرب استهلاك النطاق الترددي لحفظة AWS وغيرها من مخازن الكائنات المتوافقة مع S3 التي تسمح بالوصول إلى نقاط نهاية الحافظة الخام، لأن الدردشة تتجاوز شبكة توصيل المحتوى بالكامل؛ مما يؤدي إلى دفع رسوم خروج مباشرة من S3 لجميع حركة مرور صور المصغرات في الدردشة.
  • تسرب البنية التحتية: يتم كشف عناوين URL لتخزين الخلفية الخام (بما في ذلك أسماء الحفظة الداخلية وأحيانًا معرفات الحسابات) في حمولات JSON الخاصة بالعميل.

طلب سحب (PR):

لدي طلب سحب (PR) لإصلاح هذه المشكلة هنا:

https://github.com/discourse/discourse/pull/40419

يبدو أن Sam أضاف دالة getURLWithCDN إلى معاينة محرر الدردشة - ومع ذلك، لا أعتقد أنها تصل إلى تيار الدردشة؟

أتساءل عما إذا كان إصلاح المحرر قد يكون فشل في بعض إعدادات S3 أيضًا لأن getURLWithCDN تتعطل عند وجود تعارض في البروتوكول (// مقابل https://)؟ على أي حال، يوسع طلب السحب المذكور أعلاه عمل Sam من خلال إضافة أغلفة إلى تيار الدردشة وجعله محايدًا للبروتوكول.

حل مؤقت:

قبل أن أدرك أن هذه المشكلة تتجاوز مجرد Cloudflare، قمت بإنشاء مكون سمة خفيف الوزن. يقوم هذا المكون باعتراض نطاقات S3 الخام في عنصر DOM الخاص بالدردشة واستبدالها بنطاق شبكة توصيل المحتوى الصحيح قبل أن يحاول المتصفح تنزيلها. وهذا يوجه حركة المرور بشكل صحيح ويسد ثغرة استهلاك النطاق الترددي. وقد قمت بتكييفه ليعمل مع أي تخزين كائنات متوافق مع S3. كل ما يتطلبه الأمر هو إعدادان فقط: «عنوان URL الخام لحافظة S3» و«عنوان URL لشبكة توصيل المحتوى S3».

https://github.com/Lillinator/chat-s3-thumbnails-fix

(لا أعرف سبب تعطل روابط GitHub المضمنة هنا) تم الإصلاح الآن

5 إعجابات

على الأرجح يتعلق الأمر بنقل الموقع… لقد قمت بإعادة الخبز للتو.

إعجابَين (2)

مرحبًا، هل تم دمج طلب السحب بالفعل؟

شكرًا لك

إعجابَين (2)

الأمر الآن في انتظار مراجعة من قبل فريق بشري بعد أن قام صديقي discourse-triage-bot بإصلاح بعض الاختبارات :slight_smile:

https://github.com/discourse/discourse/pull/40419#issuecomment-4683409099

5 إعجابات

يبدو أنه تم دمجه الآن.

4 إعجابات

تم الفتح بناءً على طلب المؤلف

بالنسبة للمواقع التي تمت إضافة رموز تعبيرية مخصصة إليها، فستكون معطلة الآن في الدردشة بعد دمج الإصلاح.

على عكس صور المنشورات القياسية (التي يمكن إصلاحها باستخدام الأمر rake posts:rebake)، يتم تمرير الرموز التعبيرية المخصصة للدردشة إلى الواجهة الأمامية ديناميكيًا عبر /site.json.

إذا كانت قاعدة البيانات تحتوي على عناوين URL لـ S3 تفتقر إلى البروتوكول (مثل //bucket.endpoint...) أو تستخدم نطاقًا بأسلوب المضيف الافتراضي الذي لا يتطابق تمامًا مع متغيرات البيئة في ملف app.yml الخاص بك، فإن مُستبدل CDN الداخلي الخاص بـ Discourse يفشل بصمت. يتم تمرير عنوان URL الخام للحاوية إلى المتصفح، مما يعطل الرموز التعبيرية المخصصة في الدردشة.

كيفية الإصلاح:

لإصلاح هذه المشكلة بشكل دائم، تحتاج إلى إعادة تعيين عناوين URL الخام للحاوية لتتوافق مع عنوان URL الخاص بـ CDN في قاعدة البيانات، ثم مسح ذاكرة التخزين المؤقت للموقع حتى يتم إعادة إنشاء /site.json.

1. الدخول إلى الحاوية:

قم بالاتصال بخادمك عبر SSH ودخل إلى حاوية Discourse الخاصة بك (عادةً ما تكون app، أو web_only إذا كان لديك إعداد مكون من حاويتين).

cd /var/discourse
./launcher enter app

2. إعادة تعيين عناوين URL:

قم بتشغيل أداة remap المدمجة في Discourse. يجب عليك تشغيلها مرتين للتأكد من التقاط كل من تنسيق https:// وتنسيق // بدون بروتوكول الذي قد يتركه سكريبت الترحيل خلفه.

استبدل العناوين النائبة بعنوان URL الخام الفعلي للحاوية وعنوان URL الفعلي لـ CDN الخاص بك:

# إصلاح عناوين URL القياسية التي تبدأ بـ https://
discourse remap "https://<your-bucket>.<your-endpoint>.com" "https://cdn.your-domain.com"

# إصلاح عناوين URL بدون بروتوكول التي تبدأ بـ // (هذا هو السبب الشائع لتعطيل الرموز التعبيرية المخصصة)
discourse remap "//<your-bucket>.<your-endpoint>.com" "https://cdn.your-domain.com"

3. مسح ذاكرة التخزين المؤقت

بما أن /site.json يخزن في ذاكرة التخزين المؤقت بشكل مكثف، يجب عليك مسح ذاكرة التخزين المؤقت لـ Rails لإجبار المنتدى على تقديم عناوين URL الجديدة:

افتح وحدة تحكم Rails:

rails c

قم بتشغيل الأوامر التالية:

Rails.cache.clear
Site.clear_cache
exit

4. تحديث الصفحة

قم بتحديث صفحة المتصفح بشكل قسري (وألغِ استخدام حل العمل الخاص بمكون السمة إذا كنت لا تزال تستخدمه). يجب أن تكون الرموز التعبيرية المخصصة في الدردشة قد أُصلحت الآن وتعمل بشكل صحيح عبر CDN.

3 إعجابات

مرحباً ليلى، شكراً جزيلاً لك على عملك الرائع. الآن، أصبحت رفعاتي القديمة ومعاينات الصور تعمل بشكل متوقع بعد إعادة التوجيه المزدوجة. قبل ذلك، لم تكن صور “/admin/config/customize/themes” تعمل حتى. الآن كل شيء قد أُصلح. هذا رائع.

شكراً لك

إعجاب واحد (1)