Veröffentlicht: 6. Oktober 2020
Einige HTTP-Anfragen enthalten einen Range:-Header, der angibt, dass nur ein Teil der vollständigen Ressource zurückgegeben werden soll. Sie werden häufig für das Streamen von Audio- oder Videoinhalten verwendet, damit kleinere Media-Blöcke bei Bedarf geladen werden können, anstatt die gesamte Remotedatei auf einmal anzufordern.
Ein Service Worker ist JavaScript-Code, der sich zwischen Ihrer Web-App und dem Netzwerk befindet. Er kann ausgehende Netzwerkanfragen abfangen und Antworten darauf generieren.
Bisher haben Bereichsanfragen und Service Worker nicht gut zusammengearbeitet. Es waren besondere Maßnahmen erforderlich, um unerwünschte Ergebnisse in Ihrem Service Worker zu vermeiden. Glücklicherweise ändert sich das langsam. In Browsern, die sich korrekt verhalten, funktionieren Bereichsanfragen einfach, wenn sie über einen Service Worker weitergeleitet werden.
Worin liegt das Problem?
Betrachten Sie einen Service Worker mit dem folgenden fetch-Event-Listener, der jede eingehende Anfrage entgegennimmt und an das Netzwerk weiterleitet:
self.addEventListener('fetch', (event) => {
// The Range: header will not pass through in
// browsers that behave incorrectly.
event.respondWith(fetch(event.request));
});
In Browsern mit dem falschen Verhalten wurde der Range:-Header stillschweigend gelöscht, wenn event.request ihn enthielt. Die Anfrage, die vom Remote-Server empfangen wurde, enthält Range: nicht. Das muss nicht unbedingt zu Problemen führen, da ein Server technisch gesehen den vollständigen Antworttextkörper mit dem Statuscode 200 zurückgeben darf, auch wenn in der ursprünglichen Anfrage ein Range:-Header vorhanden ist. Dies würde jedoch dazu führen, dass mehr Daten übertragen werden, als aus Browsersicht unbedingt erforderlich sind.
Entwickler, die sich dieses Verhaltens bewusst sind, können es umgehen, indem sie explizit prüfen, ob ein Range:-Header vorhanden ist, und event.respondWith() nicht aufrufen, wenn dies der Fall ist. Dadurch wird der Service Worker effektiv aus der Antwortgenerierung entfernt und stattdessen die standardmäßige Netzwerklogik des Browsers verwendet, die weiß, wie Bereichsanfragen beibehalten werden.
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));
});
Die meisten Entwickler waren sich dessen jedoch nicht bewusst. Und es war nicht klar, warum das erforderlich sein sollte. Letztendlich war diese Einschränkung darauf zurückzuführen, dass Browser die Änderungen in der zugrunde liegenden Spezifikation, die die Unterstützung für diese Funktion hinzugefügt haben, noch nicht übernommen hatten.
Welche Fehler wurden behoben?
Browser, die sich korrekt verhalten, behalten den Range:-Header bei, wenn event.request an fetch() übergeben wird. Das bedeutet, dass der Service Worker-Code in meinem ursprünglichen Beispiel dem Remote-Server erlaubt, den Range:-Header zu sehen, wenn er vom Browser festgelegt wurde:
self.addEventListener('fetch', (event) => {
// The Range: header will pass through in browsers
// that behave correctly.
event.respondWith(fetch(event.request));
});
Der Server hat jetzt die Möglichkeit, die Bereichsanfrage richtig zu verarbeiten und eine Teilantwort mit dem Statuscode 206 zurückzugeben.
Welche Browser verhalten sich korrekt?
Aktuelle Versionen von Safari haben die richtige Funktionalität. Chrome und Edge verhalten sich ab Version 87 ebenfalls korrekt.
Im Oktober 2020 wurde dieses Verhalten in Firefox noch nicht behoben. Sie müssen es also möglicherweise berücksichtigen, wenn Sie den Code Ihres Service Workers in der Produktion bereitstellen.
Am besten prüfen Sie in der Zeile „Include range header in network request“ (Bereichsheader in Netzwerkanfrage einfügen) des Web Platform Tests-Dashboards, ob ein bestimmter Browser dieses Verhalten korrigiert hat.
Wie sieht es mit der Bereitstellung von Bereichsanfragen aus dem Cache aus?
Service Worker können viel mehr als nur eine Anfrage an das Netzwerk weiterleiten. Ein häufiger Anwendungsfall ist das Hinzufügen von Ressourcen wie Audio- und Videodateien zu einem lokalen Cache. Ein Service Worker kann dann Anfragen aus diesem Cache erfüllen und das Netzwerk vollständig umgehen.
Alle Browser, einschließlich Firefox, unterstützen die Prüfung einer Anfrage in einem fetch-Handler, die Suche nach dem Range:-Header und die lokale Erfüllung der Anfrage mit einer 206-Antwort aus einem Cache. Der Service Worker-Code zum richtigen Parsen des Range:-Headers und zum Zurückgeben nur des entsprechenden Segments der vollständigen im Cache gespeicherten Antwort ist jedoch nicht trivial.
Glücklicherweise können Entwickler, die Hilfe benötigen, auf Workbox zurückgreifen. Das ist eine Reihe von Bibliotheken, die gängige Anwendungsfälle für Service Worker vereinfachen. Das workbox-range-request module implementiert die gesamte Logik, die erforderlich ist, um Teilantworten direkt aus dem Cache bereitzustellen. Ein vollständiges Rezept für diesen Anwendungsfall finden Sie in der Workbox-Dokumentation.