8000 Service Worker incorrectly handles external Range Requests, causing an infinite loop and bypassing dataGroups configuration · Issue #62333 · angular/angular · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Service Worker incorrectly handles external Range Requests, causing an infinite loop and bypassing dataGroups configuration #62333
Closed
@Benny739

Description

@Benny739

Which @angular/* package(s) are the source of the bug?

service-worker

Is this a regression?

No

Description

Problem Description

The Angular Service Worker in v20.0.5 incorrectly handles fetch events for external URLs that contain an HTTP Range header. This leads to an infinite loop within the service worker, which the browser eventually terminates by serving the index.html file as a fallback.

This behavior makes it impossible to stream media from external CDNs using libraries like hls.js, as these rely on Range Requests to fetch video segments.

Crucially, this faulty logic has a higher precedence than the dataGroups configuration in ngsw-config.json. Any dataGroups rule intended to create a "pass-through" for external URLs (e.g., for https://*/**) is completely ignored for requests containing a Range header.

Reproduction

Setup: Create a new Angular application using Angular v20 and add @angular/pwa.

Configuration: Configure the ngsw-config.json with a "pass-through" dataGroup intended to let all external HTTPS requests go directly to the network.

JSON

// ngsw-config.json
{
// ...
"dataGroups": [
{
"name": "external-https-passthrough",
"urls": [
"https://*/**"
],
"cacheConfig": {
"maxSize": 0,
"maxAge": "0u",
"strategy": "freshness"
}
}
]
}
Action: In a component, attempt to play a video from any external CDN that delivers video via HLS or DASH. A library like hls.js will trigger requests for media segments (.mp4, .ts) which include a Range: bytes=... header.

Observation: Open the browser's developer tools and inspect the Network tab.

Expected Behavior

The dataGroups rule for https://*/** should be respected for all external data requests, including those with a Range header.

The service worker should intercept the request, match it against the dataGroup's pattern, and apply the freshness strategy, fetching the resource directly from the network.

The video player should receive the correct video segment data and playback should start correctly.

Actual Behavior

The network request for the video segment fails.

The "Size" column in the Network tab shows that the request was handled by the (ServiceWorker).

The "Response" tab for the failed request shows the content of the application's index.html file.

The hls.js library fails with a mediaError of type fragParsingError because it cannot parse the received HTML content.

Root Cause Analysis

The issue lies in the onFetch method of the Driver class in the compiled ngsw-worker.js.

JavaScript

// ngsw-worker.js (un-patched) in Driver.onFetch(event)
onFetch(event) {
const req = event.request;
// ...
if (req.headers.has("range")) {
event.respondWith(this.handleRangeRequest(req));
return; // <-- Problematic early return
}
// ...
// The logic that processes dataGroups is only reached here:
event.respondWith(this.handleFetch(event));
}
The if (req.headers.has("range")) check has high precedence and executes near the beginning of the onFetch listener.

If a request has a Range header, it immediately calls this.handleRangeRequest(req) and then returns.

This completely bypasses the main event.respondWith(this.handleFetch(event)) call at the end of the method, which is responsible for invoking the logic that evaluates the dataGroups configuration.

The handleRangeRequest method then calls await fetch(req). Since this is called from within the onFetch listener for the same request, it is re-intercepted by the service worker, causing an infinite loop.

The browser breaks this loop and serves the index.html as a fallback.

This special handling for Range Requests seems intended for serving cached media, but it incorrectly intercepts and mishandles all Range requests, including external ones it should be ignoring.

Workaround

The only viable solution is to manually patch the generated ngsw-worker.js file after the build process. By injecting a check at the very beginning of the onFetch method, the faulty logic can be bypassed for external requests.

This sed command in our build script resolves the issue:

Bash

sed -i '' "s/onFetch(event) {/onFetch(event) { const url = new URL(event.request.url); if (url.origin !== self.location.origin) { return; }/g" dist/path/to/ngsw-worker.js
This patch correctly instructs the service worker to immediately cede control for any request not originating from the application's own origin, allowing the browser to handle it normally. This happens before the problematic range header check is reached.

Environment

Angular version: 20.0.5

Angular CLI version: 20.0.5

@angular/service-worker version: 20.0.5

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw


Please provide the environment you discovered this bug in (run ng version)


Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: service-workerIssues related to the @angular/service-worker packageneeds reproductionThis issue needs a reproduction in order for the team to investigate further

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0