مدیریت درخواست‌های محدوده در یک سرویس ورکر

منتشر شده: ۶ اکتبر ۲۰۲۰

برخی از درخواست‌های HTTP حاوی یک سرآیند Range: هستند که نشان می‌دهد فقط بخشی از کل منبع باید بازگردانده شود. آن‌ها معمولاً برای پخش محتوای صوتی یا تصویری استفاده می‌شوند تا به جای درخواست کل فایل از راه دور به صورت یکجا، امکان بارگذاری بخش‌های کوچک‌تر رسانه را در صورت تقاضا فراهم کنند.

یک سرویس ورکر ، کد جاوا اسکریپتی است که بین برنامه وب شما و شبکه قرار می‌گیرد و به طور بالقوه درخواست‌های خروجی شبکه را رهگیری کرده و برای آنها پاسخ تولید می‌کند.

از نظر تاریخی، درخواست‌های محدوده و سرویس ورکرها با هم خوب کنار نمی‌آیند. لازم بوده است که اقدامات خاصی برای جلوگیری از نتایج بد در سرویس ورکرها انجام شود. خوشبختانه، این وضعیت در حال تغییر است. در مرورگرهایی که رفتار صحیحی از خود نشان می‌دهند، درخواست‌های محدوده هنگام عبور از یک سرویس ورکرها "به درستی کار می‌کنند".

مسئله چیست؟

یک سرویس ورکر با شنونده رویداد 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 برگرداند.

کدام مرورگرها به درستی رفتار می‌کنند؟

نسخه‌های اخیر سافاری عملکرد صحیحی دارند. کروم و اج، از نسخه ۸۷ به بعد ، نیز به درستی کار می‌کنند.

تا اکتبر ۲۰۲۰، فایرفاکس هنوز این مشکل را برطرف نکرده است، بنابراین ممکن است هنگام استقرار کد سرویس ورکر خود در محیط عملیاتی، هنوز نیاز به در نظر گرفتن آن داشته باشید.

بررسی ردیف «شامل سربرگ محدوده در درخواست شبکه» در داشبورد تست‌های پلتفرم وب ، بهترین راه برای تأیید این است که آیا مرورگر مورد نظر این رفتار را اصلاح کرده است یا خیر.

در مورد ارائه درخواست‌های محدوده از حافظه پنهان چطور؟

سرویس ورکرها می‌توانند کارهای بسیار بیشتری از ارسال درخواست به شبکه انجام دهند. یک مورد استفاده رایج، اضافه کردن منابعی مانند فایل‌های صوتی و تصویری به یک حافظه پنهان محلی است. سپس یک سرویس ورک می‌تواند درخواست‌های آن حافظه پنهان را انجام دهد و شبکه را به طور کامل دور بزند.

همه مرورگرها، از جمله فایرفاکس، از بررسی یک درخواست در داخل یک fetch handler، بررسی وجود هدر Range: و سپس انجام محلی درخواست با یک پاسخ 206 که از یک حافظه پنهان می‌آید، پشتیبانی می‌کنند. با این حال، کد سرویس ورکر برای تجزیه صحیح Range: و بازگرداندن تنها بخش مناسب از پاسخ کامل ذخیره شده در حافظه پنهان، کار ساده‌ای نیست.

خوشبختانه، توسعه‌دهندگانی که به کمک نیاز دارند می‌توانند به Workbox مراجعه کنند، که مجموعه‌ای از کتابخانه‌ها است که موارد استفاده رایج سرویس ورکرها را ساده می‌کند. workbox-range-request module تمام منطق لازم برای ارائه پاسخ‌های جزئی را مستقیماً از حافظه پنهان پیاده‌سازی می‌کند. دستورالعمل کامل این مورد استفاده را می‌توانید در مستندات Workbox بیابید.