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

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

تحتوي بعض طلبات 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.