Fetch Interception, also known as Foreign Fetch and Fallthroug Fetch is a mechanism for service workers to handle fetch requests from clients that are not controlled by the service worker.
The proposed API involves some new API in the service worker spec, as well as some minor modifications to the fetch spec.
The first part is an API to allow a service worker to explicitly opt-in to intercepting fetch requests. To enabled this, each service worker registration will have an associated list of interception scopes. These scopes should be inside (or equal to) the overall scope of the registration. A new method is added to the activate event to allow setting this list:
[Constructor(DOMString type, optional ExtendableEventInit eventInitDict), Exposed=ServiceWorker]
interface ActivateEvent : ExtendableEvent {
void interceptFetchRequests(optional (USVString or sequence<USVString>) scopes);
};
When dispatching an activate event the list of interception scopes is cleared. If the interceptFetchRequests
method is subsequently called, the list of interception scopes is set to the passed scope or scopes, or set to the scope of the registration is no explicit scopes are passed.
Another (maybe cleaner) option would be to have the list of interception scopes stored on a per service worker base. In that case it could be the install event instead of the activate event that would have the method to register to receive these events.
A couple of new algorithms should also be added to the service worker spec:
- Input
- `requestURL`, an absolute URL
- Output
- `registration`, a service worker registration
- Run the following steps atomically.
- Let
registration
be the result of running the Match Service Worker Registration algorithm withrequestURL
as parameter. - If
registration
is null, return null. - Let
requestURLString
be the serializedrequestURL
- For each [[scope]] in the registrations interception scopes:
- If
requestURLString
starts with [[scope]], then: 1. Return registration - Return null.
This first finds a potential service worker registration candidate by checking its scope, and then checks if the interception scopes of that service worker include the request URL. I think this behavior is more sensible than the other option, which would be to instead try to find the service worker registration which has the longest interception scope that matches the request.
Thes two would be different in the case where SW1 has scope /scope
with interception scope /scope/nested/foo
while SW2 has scope /scope/nested
and interception scope /scope/nested
. In the algorithm as described requests for /scope/nested/foo/bar
would be handled by SW2, while the other option would be that this should behandled by SW1.
- Input
- `request`, a request
- Output
- `respone`, a service worker registration
Not in formal algorithm form yet, but this would do something like the following:
- Look up registration for the request using Match Service Worker Registration for Fetch Interception algorithm
- If requests client is a service worker, make sure it isn't a worker for the same SW registration (or maybe the entire origin?)
- Create a FetchEvent instance for the request (or maybe a modified version of the request to hide data we don't want to expose to the SW). This FetchEvent will have a null client.
- Dispatch 'fetch' FetchEvent to active worker. Or maybe this should be dispatched as some other event type.
Add a new step to the HTTP fetch algorithm between step 2 and 3, something like this:
2½. If response is null, and the request's skip-service-worker flag is unset run these substeps:
- Set response to the result of invoking Handle Fetch Interception for request.
- In some cases return a network error.