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

Upewnij się, że pracownik obsługi klienta wie, co robić, gdy zostanie poproszony o odpowiedź częściową.

Niektóre żądania HTTP zawierają nagłówek Range:, który wskazuje, że zwrócona powinna zostać tylko część pełnego zasobu. Są one często używane do strumieniowego przesyłania treści audio lub wideo, aby umożliwić wczytywanie mniejszych fragmentów multimediów na żądanie zamiast żądania całego pliku zdalnego naraz.

Skrypt service worker to kod JavaScript, który działa między aplikacją internetową a siecią i może przechwytywać wychodzące żądania sieci oraz generować dla nich odpowiedzi.

Dotychczas żądania zakresu i skrypty service worker nie współpracowały ze sobą dobrze. Konieczne było podjęcie specjalnych działań, aby uniknąć niepożądanych skutków w Twoim serwisie. Na szczęście sytuacja zaczyna się zmieniać. W przeglądarkach, które działają prawidłowo, żądania zakresu będą „działać” po prostu, gdy będą przechodzić przez skrypt service worker.

Na czym polega problem?

Rozważ usługę w tle z tym odbiornikiem zdarzeń fetch, który przejmuje 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 przypadku przeglądarek z nieprawidłowym działaniem, jeśli event.request zawiera nagłówek Range:, ten nagłówek jest po cichu usuwany. Żądanie odebrane przez serwer zdalny nie zawierałoby w ogóle Range:. Niekoniecznie musi to „zepsuć” cokolwiek, ponieważ serwer może technicznie zwrócić pełny tekst odpowiedzi z kodem stanu 200, nawet jeśli w pierwotnym żądaniu występuje nagłówek Range:. Z perspektywy przeglądarki spowoduje to jednak przesłanie większej ilości danych niż jest to ściśle konieczne.

Deweloperzy, którzy wiedzieli o tym zachowaniu, mogli je obejść, wyraźnie sprawdzając obecność nagłówka Range: i nie wywołując funkcji event.respondWith(), jeśli jest on obecny. Dzięki temu usługa nie będzie już uczestniczyć w generowaniu odpowiedzi, a zamiast niej będzie używana domyślna logika sieciowa przeglądarki, która wie, jak zachować żądania 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));
});

Można jednak śmiało powiedzieć, że większość deweloperów nie była świadoma konieczności wykonania tej czynności. Nie było też jasne, dlaczego to jest wymagane. Ostatecznie to ograniczenie było spowodowane tym, że przeglądarki musiały dostosować się do zmian w podstawowej specyfikacji, które dodały obsługę tej funkcji.

Co zostało naprawione?

Przeglądarki, które działają prawidłowo, zachowują nagłówek Range:, gdy event.request jest przekazywany do fetch(). Oznacza to, że kod usługi w pierwszym przykładzie pozwoli serwerowi zdałem wyświetlić 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 możliwość prawidłowego obsłużenia żądania zakresu i zwrócenia częściowej odpowiedzi z kodem stanu 206.

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

W najnowszych wersjach Safari funkcja działa prawidłowo. Chrome i Edge od wersji 87 również działają prawidłowo.

W październiku 2020 r. Firefox nie naprawił jeszcze tego zachowania, więc podczas wdrażania kodu usługi w wersji produkcyjnej może być konieczne uwzględnienie tego problemu.

Najlepszym sposobem na sprawdzenie, czy dany przeglądarka naprawiła to zachowanie, jest sprawdzenie wiersza „Uwzględnij nagłówek zakresu w żądaniu sieci” na panelu Testy platformy internetowej.

Co z obsługą żądań zakresu z pamięci podręcznej?

Usługa typu service worker może zrobić znacznie więcej niż tylko przekazać żądanie do sieci. Typowym przypadkiem użycia jest dodawanie zasobów, takich jak pliki audio i wideo, do lokalnej pamięci podręcznej. Następnie usługa może obsługiwać żądania z tej pamięci podręcznej, całkowicie pomijając sieć.

Wszystkie przeglądarki, w tym Firefox, obsługują sprawdzanie żądania w obiekcie fetch, sprawdzanie obecności nagłówka Range:, a następnie lokalne wypełnianie żądania za pomocą 206 odpowiedzi pochodzącej z pamięci podręcznej. Kod usługi, który ma poprawnie zanalizować nagłówek Range: i zwrócić tylko odpowiedni segment pełnej odpowiedzi z pamięci podręcznej, nie jest jednak prosty.

Na szczęście deweloperzy, którzy potrzebują pomocy, mogą skorzystać z Workbox, czyli zestawu bibliotek upraszczających typowe przypadki użycia usług działających w tle. workbox-range-request module implementuje całą logikę niezbędną do wyświetlania częściowych odpowiedzi bezpośrednio z poziomu pamięci podręcznej. Pełny przepis na to zastosowanie znajdziesz w dokumentacji Workboxa.

Baner powitalny w tym poście pochodzi od Natalie Rhea Riggs z Unsplash.