معالجة طلبات النطاق في مشغّل الخدمات

تأكَّد من أنّ عامل الخدمة يعرف ما يجب فعله عند طلب استجابة جزئية.

تحتوي بعض طلبات HTTP على عنوان Range:، ما يشير إلى أنّه يجب عرض جزء فقط من المورد الكامل. ويتم استخدامها عادةً لبث محتوى صوتي أو فيديو للسماح بتحميل أجزاء أصغر من الوسائط عند الطلب، بدلاً من طلب الملف البعيد بالكامل دفعة واحدة.

مشغّل الخدمات هو رمز JavaScript يقع بين تطبيق الويب والشبكة، ما قد يؤدي إلى اعتراض طلبات الشبكة الصادرة وإنشاء ردود لها.

في السابق، لم تكن طلبات النطاقات ومشغّلات الخدمات تعمل معًا بشكل جيد. كان من الضروري اتّخاذ خطوات خاصة لتجنُّب النتائج السيئة في الخدمة العاملة. لحسن الحظ، بدأ هذا الوضع يتغيّر. في المتصفّحات التي تعمل بالشكل الصحيح، سيتم "تشغيل" طلبات النطاقات عند تمريرها عبر مشغّل خدمة.

ما هي المشكلة؟

لنفترض أنّ لديك عامل خدمة يتضمّن مستمع أحداث fetch التالي الذي يتلقّى كل طلب وارد ويمرّره إلى الشبكة:

self.addEventListener('fetch', (event) => {
  // The Range: header will not pass through in
  // browsers that behave incorrectly.
  event.respondWith(fetch(event.request));
});

في المتصفّحات التي تتضمّن السلوك غير الصحيح، إذا كان event.request يتضمّن عنوان Range:، سيتم حذف هذا العنوان بدون إشعار. لن يتضمّن الطلب الذي تلقّاه الخادم البعيد Range: على الإطلاق. ولن يؤدي ذلك بالضرورة إلى "تعطُّل" أيّ شيء، لأنّه يُسمح للخادم فنيًا بعرض نص الاستجابة الكامل، مع رمز الحالة 200، حتى في حال توفّر عنوان Range: في الطلب الأصلي. ولكن سيؤدي ذلك إلى نقل بيانات أكثر من اللازم من وجهة نظر المتصفّح.

يمكن للمطوّرين الذين كانوا على دراية بهذا السلوك تجنُّب حدوثه من خلال التحقّق صراحةً من توفّر عنوان Range: وعدم استدعاء event.respondWith() إذا كان متوفّرًا. من خلال إجراء ذلك، يزيل العامل في الخدمة نفسه بفعالية من عملية إنشاء الاستجابة، ويتم استخدام منطق الاتصال بالإنترنت التلقائي للمتصفح الذي يعرف كيفية الحفاظ على طلبات النطاقات بدلاً من ذلك.

self.addEventListener('fetch', (event) => {
  // Return without calling event.respondWith()
  // if this is a range request.
  if (event.request.headers.has('range')) {
    return;
  }

  event.respondWith(fetch(event.request));
});

نؤكّد لك أنّ معظم المطوّرين لم يكونوا على دراية بضرورة اتّخاذ هذا الإجراء. ولم يكن واضحًا لماذا يجب أن يكون ذلك مطلوبًا. في النهاية، كان هذا القيد ناتجًا عن حاجة المتصفّحات إلى مواكبة التغييرات في المواصفات الأساسية، ما أضاف إمكانية استخدام هذه الوظيفة.

ما هي المشاكل التي تم حلّها؟

تحافظ المتصفّحات التي تعمل بشكل صحيح على عنوان Range: عند تمرير event.request إلى fetch(). وهذا يعني أنّ رمز مشغّل الخدمات في المثال الأوّلي سيسمح للخادم البعيد بالاطّلاع على عنوان Range:، إذا تم ضبطه من خلال المتصفّح:

self.addEventListener('fetch', (event) => {
  // The Range: header will pass through in browsers
  // that behave correctly.
  event.respondWith(fetch(event.request));
});

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

فما هي المتصفحات التي تعمل بشكل صحيح؟

تعمل الإصدارات الحديثة من Safari بشكل صحيح. يعمل Chrome وEdge بشكل صحيح أيضًا، بدءًا من الإصدار 87.

اعتبارًا من تشرين الأول (أكتوبر) 2020، لم يعالج Firefox هذا السلوك بعد، لذا قد يظل عليك مراعاة ذلك أثناء نشر رمز عامل الخدمة في قناة الإصدار العلني.

إنّ التحقّق من صف "تضمين عنوان النطاق في طلب الشبكة" ضمن لوحة بيانات اختبارات منصّة الويب هو أفضل طريقة للتأكّد مما إذا كان متصفّح معيّن قد صحّح هذا السلوك أم لا.

ماذا عن طلبات نطاق العرض من ذاكرة التخزين المؤقت؟

يمكن لعمال الخدمة تنفيذ إجراءات أكثر من مجرد تمرير طلب إلى الشبكة. ومن حالات الاستخدام الشائعة إضافة موارد، مثل ملفات الصوت والفيديو، إلى ذاكرة تخزين مؤقت محلي. ويمكن بعد ذلك لعامل الخدمة تنفيذ الطلبات من ذاكرة التخزين المؤقت هذه، بدون الحاجة إلى الاتصال بالشبكة.

تتيح جميع المتصفّحات، بما في ذلك Firefox، فحص طلب داخل معالج fetch، والتأكّد من توفّر عنوان Range:، ثم تنفيذ الطلب على الجهاز من خلال استجابة 206 الواردة من ذاكرة التخزين المؤقت. مع ذلك، إنّ رمز مشغّل الخدمات الذي يتيح تحليل عنوان Range: بشكل صحيح وعرض الجزء المناسب فقط من الاستجابة المخزّنة مؤقتًا الكاملة ليس بسيطًا.

لحسن الحظ، يمكن للمطوّرين الذين يريدون بعض المساعدة الاستعانة بـ Workbox، وهي مجموعة من المكتبات التي تبسّط حالات استخدام مهام الخدمة الشائعة. تنفِّذ workbox-range-request module جميع المنطق اللازم لعرض الاستجابات الجزئية مباشرةً من ذاكرة التخزين المؤقت. يمكن العثور على طريقة كاملة لاستخدام هذه الحالة في مستندات Workbox.

الصورة الرئيسية في هذه المشاركة هي من تصميم ناتالي ريا ريجز على Unsplash.