I'm using a service worker on a WordPress site and it's messing up the redirections from https://example.com/page to https://example.com/page/.
After the first load, going to the URL without the trailing slash Blink browsers say "This site can't be reached" and Firefox says "Corrupted content error".
Based on my reading of https://medium.com/@boopathi/service-workers-gotchas-44bec65eab3f#.hf3r4pbcs and How to alter the headers of a Request? I think I have to detect when a response is 3xx and set the redirect mode to manual.
However nothing I've tried based on my research has worked. How do I fix this?
Current service worker file:
var cacheName = 'v14';
var urlsToCache = [
// list of URLs to precache
];
self.addEventListener('install', event => {
function onInstall(event) {
return caches.open(cacheName)
.then(cache => cache.addAll(urlsToCache));
}
event.waitUntil(
onInstall(event)
.then(() => self.skipWaiting())
);
});
self.addEventListener('activate', event => {
function onActivate (event) {
return caches.keys()
.then(cacheKeys => {
var oldCacheKeys = cacheKeys.filter(key => key.indexOf(cacheName) !== 0);
var deletePromises = oldCacheKeys.map(oldKey => caches.delete(oldKey));
return Promise.all(deletePromises);
})
}
event.waitUntil(
onActivate(event)
.then(() => self.clients.claim ())
);
});
self.addEventListener('fetch', event => {
function onFetch (event) {
// Let's not interfere with requests for stuff that doesn't need to be cached
// or could prevent access to admin if it is
if (event.request.url.match(/wp-admin/) || event.request.url.match(/wp-login/) || event.request.url.match(/preview=true/) || event.request.url.match(/wp-includes/) || event.request.url.match(/plugins/) || event.request.url.match(/google-analytics/) || event.request.url.match(/gravatar\.com/) || event.request.url.match(/login/) || event.request.url.match(/admin/) || event.request.method !== 'GET') {
return;
}
// Determine type of asset
var request = event.request,
acceptHeader = request.headers.get('Accept'),
resourceType = 'static';
if(acceptHeader.indexOf('text/html') !== -1) {
resourceType = 'content';
} else if(acceptHeader.indexOf('image') !== -1) {
resourceType = 'image';
}
// Network first for HTML and images
if(resourceType === 'content') {
event.respondWith(fetch(request.url, {
method: request.method,
headers: request.headers,
mode: 'same-origin', // need to set this properly
credentials: request.credentials,
redirect: 'manual'
})
.then(response => addToCache(request, response)) // read through caching
.catch(() => fetchFromCache(event))
.catch(() => offlineResponse(resourceType))
)
}
// Cache first for static assets
else if(resourceType === 'static' || resourceType === 'image') {
event.respondWith(fetchFromCache(event)
.catch(() => fetch(request))
.then(response => addToCache(request, response))
.catch(() => offlineResponse(resourceType))
)
}
}
onFetch(event);
});
function addToCache(request, response) {
if(response.ok) { // only 200s
var copy = response.clone(); // Because responses can only be used once
caches.open(cacheName)
.then(cache => {
cache.put(request, copy);
});
return response;
}
}
function fetchFromCache (event) {
return caches.match(event.request)
.then(response => {
if(!response) {
// A synchronous error that will kick off the catch handler
throw Error('${event.request.url} not found in cache');
}
return response;
});
}
function offlineResponse (resourceType) {
if(resourceType === 'content') {
return caches.match('/offline/');
}
return undefined;
}
addToCache()
won't return anything if !response.ok (such as redirects). Also, you might wantevent.respondWith(fetch(request))
since you don't seem to be transforming the request? – mjsif
fixed it. Thanks :) – Derek Johnson