Obsługa żądań dotyczących zakresu w instancji service worker

Upewnij się, że skrypt service worker wie, co zrobić, gdy zostanie zażądana odpowiedź częściowa.

Niektóre żądania HTTP zawierają nagłówek Range:, który wskazuje, że należy zwrócić tylko część pełnego zasobu. Są one zwykle używane do strumieniowego przesyłania treści audio lub wideo, co pozwala na ładowanie mniejszych fragmentów multimediów na żądanie, zamiast wysyłania żądań dotyczących całego pliku zdalnego.

Skrypt service worker to kod JavaScript umieszczony między aplikacją internetową a siecią. Może on przechwytywać wychodzące żądania sieciowe i generować dla nich odpowiedzi.

Dawniej żądania dotyczące zakresu i mechanizmy Service Worker nie współpracowały ze sobą dobrze. Aby uniknąć negatywnych wyników skryptu service worker, musisz podjąć dodatkowe kroki. Na szczęście to już się zmienia. W przeglądarkach, które wykazują prawidłowe działanie, żądania dotyczące zakresów „będą działać” podczas przekazywania przez skrypt service worker.

Na czym polega problem?

Rozważmy skrypt service worker z detektorem zdarzeń fetch, który pobiera każde przychodzące żądanie i przekazuje je do sieci:

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

W przeglądarkach o nieprawidłowym działaniu, jeśli nagłówek event.request zawiera nagłówek Range:, jest on pomijany bez powiadomienia. Żądanie odebrane przez serwer zdalny w ogóle nie zawierało parametru Range:. Nie musi to spowodować uszkodzenia czegokolwiek, ponieważ serwer może technicznie zwracać pełną treść odpowiedzi z kodem stanu 200, nawet jeśli w pierwotnym żądaniu znajduje się nagłówek Range:. Spowodowałoby to przeniesienie większej ilości danych, niż jest to bezwzględnie konieczne z punktu widzenia przeglądarki.

Deweloperzy, którzy byli świadomi tego zachowania, mogą go obejść, wyraźnie sprawdzając nagłówek Range: i nie wywołując metody event.respondWith(), jeśli taki istnieje. W ten sposób mechanizm Service Worker efektywnie usuwa się z obrazu generowania odpowiedzi, a zamiast niego używana jest domyślna logika sieciowa przeglądarki, która potrafi zachować żądania dotyczące zakresu.

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));
});

Trzeba jednak przyznać, że większość deweloperów nie zdawała sobie sprawy z tej potrzeby. Nie było też jasne, dlaczego to konieczne. Ostatecznie ograniczenie to wynikało z tego, że przeglądarki musiały dostosować się do zmian w specyfikacji, które dodały obsługę tej funkcji.

Na czym polegają problemy?

Prawidłowo działające przeglądarki zachowują nagłówek Range: po przekazaniu metody event.request do fetch(). Oznacza to, że kod skryptu service worker z mojego początkowego przykładu pozwoli serwerowi zdalnemu zobaczyć nagłówek Range:, jeśli został on ustawiony przez przeglądarkę:

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

Serwer ma teraz szansę prawidłowo obsłużyć żądanie dotyczące zakresu i zwrócić częściową odpowiedź z kodem stanu 206.

Które przeglądarki działają prawidłowo?

Najnowsze wersje Safari mają prawidłowe funkcje. Chrome i Edge, począwszy od wersji 87, również działają poprawnie.

Od października 2020 r. w Firefoksie ten problem nie został jeszcze wyeliminowany, więc nadal może być konieczne jego uwzględnienie podczas wdrażania kodu skryptu service worker w środowisku produkcyjnym.

Sprawdzanie wiersza „Uwzględnij nagłówek zakresu w żądaniu sieciowym” w panelu Testy platformy internetowej to najlepszy sposób na sprawdzenie, czy dana przeglądarka poprawiła ten błąd.

Co z żądaniami zakresu obsługi z pamięci podręcznej?

Skrypty service worker mogą robić znacznie więcej niż tylko przekazywać żądania do sieci. Typowym przypadkiem użycia jest dodanie zasobów, takich jak pliki audio i wideo, do lokalnej pamięci podręcznej. Skrypt service worker może następnie realizować żądania z tej pamięci podręcznej, całkowicie omijając sieć.

Wszystkie przeglądarki, w tym Firefox, obsługują sprawdzanie żądania w module obsługi fetch, sprawdzanie obecności nagłówka Range:, a następnie lokalne realizowanie żądania za pomocą odpowiedzi 206 z pamięci podręcznej. Jednak kod skryptu service worker pozwala na prawidłową analizę nagłówka Range: i zwracanie tylko odpowiedniego segmentu pełnej odpowiedzi zapisanej w pamięci podręcznej.

Na szczęście deweloperzy, którzy potrzebują pomocy, mogą skorzystać z Workbox – zestawu bibliotek, który upraszcza typowe przypadki użycia tych skryptów. workbox-range-request module implementuje wszystkie mechanizmy logiczne niezbędne do wyświetlania odpowiedzi częściowych bezpośrednio z pamięci podręcznej. Pełny przepis na ten przypadek użycia znajdziesz w dokumentacji Workbox.

Głównym zdjęciem tego posta jest Natalie Rhea Riggs w aplikacji Unsplash.