التعامل مع طلبات النطاق في عامل الخدمة

تاريخ النشر: 6 تشرين الأول (أكتوبر) 2020

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