I've been trying to use service workers for (what seems like hours & hours), to attach a simple header to all requests. Whats frustrating is, it sort of works.
Attempt 1:
self.addEventListener("fetch", event => {
const modifiedHeaders = new Headers({
...event.request.headers,
'API-Key': '000000000000000000001'
});
const modifiedRequest = new Request(event.request, {
headers: modifiedHeaders,
});
event.respondWith((async () => {
return fetch(modifiedRequest);
})());
});
The above code works for HTML files however for CSS & JS files I get the follow error
ReferenceError: headers is not defined
If I disable the header requirement the page loads with images and javascript and I can interact with it like normal.
Attempt 2:
var req = new Request(event.request.url, {
headers: {
...event.request.headers,
'API-Key': '000000000000000000001'
},
method: event.request.method,
mode: event.request.mode,
credentials: event.request.credentials,
redirect: event.request.redirect,
referrer: event.request.referrer,
referrerPolicy: event.request.referrerPolicy,
bodyUsed: event.request.bodyUsed,
cache: event.request.cache,
destination: event.request.destination,
integrity: event.request.integrity,
isHistoryNavigation: event.request.isHistoryNavigation,
keepalive: event.request.keepalive
});
This attempt, I simply built a new request, which successfully included the new header on CSS & JS file requests. However, When I do a POST or redirect, things stop working and behave strange.
What is the correct approach for this? I feel that attempt 1 is the better path, but I can't seem to create the Headers object on the request no matter what I do.
The version of chrome I am using is
Version 78.0.3904.70 (Official Build) (64-bit)
The site is an internal developer tool so cross browser compatibility isn't required. So I'm happy to load any additional libs / enable experimental features etc.
mode
of the original request in both of your attemptsFor embedded resources where the request is initiated from markup (unless the crossorigin attribute is present) the request is in most cases made using the no-cors
mode which only allows a very limited specific set of simple headers.
no-cors — Prevents the method from being anything other than HEAD, GET or POST, and the headers from being anything other than simple headers. If any ServiceWorkers intercept these requests, they may not add or override any headers except for those that are simple headers...
Source and more info on request modes: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
Simple headers are the following ones: accept
(only some values), accept-language
, content-language
(only some values), content-type
.
Source: https://fetch.spec.whatwg.org/#simple-header:
You need to make sure to set the mode to something other than no-cors
when creating the modified request. You can pick either cors
or same-origin
, depending on whether you want to allow cross-origin requests. (The navigate
mode is reserved for navigation only and it is not possible to create a request with that mode.)
The request issued when navigating to a new page uses the navigate
mode. Chrome does not allow creating requests with this mode using the new Request()
constructor, but seems to automatically silently use the same-origin
mode when an existing request with the navigate
mode is passed to the constructor as a parameter. This means that your first (HTML load) modified request had same-origin
mode, while the CSS and JS load requests had the no-cors
mode.
'use strict';
/* Auxiliary function to log info about requests to the console */
function logRequest(message, req) {
const headersString = [...req.headers].reduce((outputString, val) => `${outputString}\n${val[0]}: ${val[1]}`, 'Headers:');
console.log(`${message}\nRequest: ${req.url}\nMode: ${req.mode}\n${headersString}\n\n`);
}
self.addEventListener('fetch', (event) => {
logRequest('Fetch event detected', event.request);
const modifiedHeaders = new Headers(event.request.headers);
modifiedHeaders.append('API-Key', '000000000000000000001');
const modifiedRequestInit = { headers: modifiedHeaders, mode: 'same-origin' };
const modifiedRequest = new Request(event.request, modifiedRequestInit);
logRequest('Modified request', modifiedRequest);
event.respondWith((async () => fetch(modifiedRequest))());
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With