kopia lustrzana https://gitlab.com/rysiekpl/libresilient
important hotfix: config.json now properly cached, SW init performed reliably after SW re-start (ref. #31)
rodzic
387009782e
commit
6fe4e94199
|
@ -92,11 +92,11 @@ self.log = function(component, ...items) {
|
|||
|
||||
|
||||
/**
|
||||
* verifying a config JSON
|
||||
* verifying and loading a config JSON
|
||||
*
|
||||
* cdata - config data to verify
|
||||
*/
|
||||
let verifyConfigData = (cdata) => {
|
||||
let loadConfigData = (cdata) => {
|
||||
// basic check for the plugins field
|
||||
if ( !("plugins" in cdata) || ! Array.isArray(cdata.plugins) ) {
|
||||
self.log('service-worker', 'fetched config does not contain a valid "plugins" field')
|
||||
|
@ -107,23 +107,34 @@ let verifyConfigData = (cdata) => {
|
|||
self.log('service-worker', 'fetched config does not contain a valid "loggedComponents" field')
|
||||
return false;
|
||||
}
|
||||
// defaultPluginTimeout optional
|
||||
// defaultPluginTimeout is optional
|
||||
if ("defaultPluginTimeout" in cdata) {
|
||||
if (!Number.isInteger(cdata.defaultPluginTimeout)) {
|
||||
self.log('service-worker', 'fetched config contains invalid "defaultPluginTimeout" data (integer expected)')
|
||||
return false;
|
||||
}
|
||||
// safe to apply defaultPluginTimeout
|
||||
self.LibResilientConfig.defaultPluginTimeout = cdata.defaultPluginTimeout
|
||||
}
|
||||
// safe to apply main config data
|
||||
self.LibResilientConfig.plugins = cdata.plugins
|
||||
self.LibResilientConfig.loggedComponents = cdata.loggedComponents
|
||||
// we're good
|
||||
return true;
|
||||
}
|
||||
|
||||
// flag signifying the SW has been initialized already
|
||||
var initDone = false
|
||||
|
||||
// load the plugins
|
||||
//
|
||||
// everything in a try-catch block
|
||||
// so that we get an informative message if there's an error
|
||||
let initServiceWorker = async () => {
|
||||
// if init has already been done, skip!
|
||||
if (initDone) {
|
||||
self.log('service-worker', 'skipping service-worker init, already done')
|
||||
return false;
|
||||
}
|
||||
// everything in a try-catch block
|
||||
// so that we get an informative message if there's an error
|
||||
try {
|
||||
|
||||
// get the config
|
||||
|
@ -134,19 +145,37 @@ let initServiceWorker = async () => {
|
|||
// TODO: providing config directly from browser-side control script via postMessage?
|
||||
// TODO: `updateViaCache=imports` allows at least config.json to be updated using the cache plugin?
|
||||
try {
|
||||
//self.importScripts(self.registration.scope + "config.json")
|
||||
var cdata = await fetch(self.registration.scope + "config.json")
|
||||
if (cdata.status != 200) {
|
||||
// config.json URL
|
||||
var configURL = self.registration.scope + "config.json"
|
||||
// we need to know if the config was already cached
|
||||
var wasCached = true
|
||||
// get the config file, cached or otherwise
|
||||
var cresponse = await caches.match(configURL)
|
||||
if (cresponse != undefined) {
|
||||
self.log('service-worker', `config file retrieved from cache.`)
|
||||
} else {
|
||||
self.log('service-worker', `config file not found in cache, fetching.`)
|
||||
wasCached = false
|
||||
cresponse = await fetch(configURL)
|
||||
}
|
||||
// check for sanity
|
||||
if (cresponse.status != 200) {
|
||||
self.log('service-worker', `failed to fetch config (${cdata.status} ${cdata.statusText}).`)
|
||||
} else {
|
||||
cdata = await cdata.json()
|
||||
if (verifyConfigData(cdata)) {
|
||||
self.LibResilientConfig.plugins = cdata.plugins
|
||||
self.LibResilientConfig.loggedComponents = cdata.loggedComponents
|
||||
if ("defaultPluginTimeout" in cdata) {
|
||||
self.LibResilientConfig.defaultPluginTimeout = cdata.defaultPluginTimeout
|
||||
}
|
||||
// process the data
|
||||
cdata = await cresponse.clone().json()
|
||||
if (loadConfigData(cdata)) {
|
||||
self.log('service-worker', 'config loaded.')
|
||||
// cache the valid config.json
|
||||
if (!wasCached) {
|
||||
try {
|
||||
var cache = await caches.open('v1')
|
||||
await cache.put(configURL, cresponse)
|
||||
self.log('service-worker', 'config cached.')
|
||||
} catch(e) {
|
||||
self.log('service-worker', `failed to cache config: ${e}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.log('service-worker', 'ignoring invalid config, using defaults.')
|
||||
}
|
||||
|
@ -251,6 +280,7 @@ let initServiceWorker = async () => {
|
|||
|
||||
// inform
|
||||
self.log('service-worker', `DEBUG: Strategy in use: ${self.LibResilientPlugins.map(p=>p.name).join(', ')}`)
|
||||
initDone = true;
|
||||
|
||||
} catch(e) {
|
||||
// we only get a cryptic "Error while registering a service worker"
|
||||
|
@ -258,6 +288,7 @@ let initServiceWorker = async () => {
|
|||
console.error(e)
|
||||
throw e
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -718,80 +749,83 @@ let getResourceThroughLibResilient = (url, init, clientId, useStashed=true, doSt
|
|||
\* ========================================================================= */
|
||||
self.addEventListener('install', async (event) => {
|
||||
event.waitUntil(initServiceWorker())
|
||||
// TODO: Might we want to have a local cache?
|
||||
// "COMMIT_UNKNOWN" will be replaced with commit ID
|
||||
self.log('service-worker', "0. Installed LibResilient Service Worker (commit: COMMIT_UNKNOWN).");
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
self.addEventListener('activate', async event => {
|
||||
self.log('service-worker', "1. Activated LibResilient Service Worker (commit: COMMIT_UNKNOWN).");
|
||||
// TODO: should we do some plugin initialization here?
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
// if event.resultingClientId is available, we need to use this
|
||||
// otherwise event.clientId is what we want
|
||||
// ref. https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/resultingClientId
|
||||
var clientId = (event.clientId !== null) ? event.clientId : 'unknown-client'
|
||||
if (event.resultingClientId) {
|
||||
clientId = event.resultingClientId
|
||||
// yeah, we seem to have to send the client their clientId
|
||||
// because there is no way to get that client-side
|
||||
// and we need that for sane messaging later
|
||||
//
|
||||
// so let's also send the plugin list, why not
|
||||
//
|
||||
// *sigh* JS is great *sigh*
|
||||
self.clients
|
||||
.get(clientId)
|
||||
.then((client)=>{
|
||||
if (client !== null) {
|
||||
try {
|
||||
client.postMessage({
|
||||
clientId: clientId,
|
||||
plugins: self.LibResilientPlugins.map((p)=>{return p.name}),
|
||||
serviceWorker: 'COMMIT_UNKNOWN'
|
||||
})
|
||||
} catch(err) {
|
||||
self.log("service-worker", `postMessage failed for client: ${client}\n- Error message: ${err}`)
|
||||
self.addEventListener('fetch', async event => {
|
||||
return void event.respondWith(async function () {
|
||||
// initialize the SW
|
||||
await initServiceWorker()
|
||||
// if event.resultingClientId is available, we need to use this
|
||||
// otherwise event.clientId is what we want
|
||||
// ref. https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/resultingClientId
|
||||
var clientId = (event.clientId !== null) ? event.clientId : 'unknown-client'
|
||||
if (event.resultingClientId) {
|
||||
clientId = event.resultingClientId
|
||||
// yeah, we seem to have to send the client their clientId
|
||||
// because there is no way to get that client-side
|
||||
// and we need that for sane messaging later
|
||||
//
|
||||
// so let's also send the plugin list, why not
|
||||
//
|
||||
// *sigh* JS is great *sigh*
|
||||
self.clients
|
||||
.get(clientId)
|
||||
.then((client)=>{
|
||||
if (client !== null) {
|
||||
try {
|
||||
client.postMessage({
|
||||
clientId: clientId,
|
||||
plugins: self.LibResilientPlugins.map((p)=>{return p.name}),
|
||||
serviceWorker: 'COMMIT_UNKNOWN'
|
||||
})
|
||||
} catch(err) {
|
||||
self.log("service-worker", `postMessage failed for client: ${client}\n- Error message: ${err}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// counter!
|
||||
if (typeof self.activeFetches.get(clientId) !== "number") {
|
||||
self.activeFetches.set(clientId, 0)
|
||||
}
|
||||
|
||||
// info
|
||||
self.log('service-worker', "Fetching!",
|
||||
"\n+-- url :", event.request.url,
|
||||
"\n+-- clientId :", event.clientId,
|
||||
"\n+-- resultingClientId:", event.resultingClientId,
|
||||
"\n +-- activeFetches[" + clientId + "]:", self.activeFetches.get(clientId)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// counter!
|
||||
if (typeof self.activeFetches.get(clientId) !== "number") {
|
||||
self.activeFetches.set(clientId, 0)
|
||||
}
|
||||
|
||||
// info
|
||||
self.log('service-worker', "Fetching!",
|
||||
"\n+-- url :", event.request.url,
|
||||
"\n+-- clientId :", event.clientId,
|
||||
"\n+-- resultingClientId:", event.resultingClientId,
|
||||
"\n +-- activeFetches[" + clientId + "]:", self.activeFetches.get(clientId)
|
||||
)
|
||||
|
||||
// External requests go through a regular fetch()
|
||||
if (!event.request.url.startsWith(self.location.origin)) {
|
||||
self.log('service-worker', 'External request; current origin: ' + self.location.origin)
|
||||
return void event.respondWith(fetch(event.request));
|
||||
}
|
||||
// External requests go through a regular fetch()
|
||||
if (!event.request.url.startsWith(self.location.origin)) {
|
||||
self.log('service-worker', 'External request; current origin: ' + self.location.origin)
|
||||
return void event.respondWith(fetch(event.request));
|
||||
}
|
||||
|
||||
// Non-GET requests go through a regular fetch()
|
||||
if (event.request.method !== 'GET') {
|
||||
return void event.respondWith(fetch(event.request));
|
||||
}
|
||||
|
||||
// clean the URL, removing any fragment identifier
|
||||
var url = event.request.url.replace(/#.+$/, '');
|
||||
|
||||
// get the init object from Request
|
||||
var init = initFromRequest(event.request)
|
||||
// Non-GET requests go through a regular fetch()
|
||||
if (event.request.method !== 'GET') {
|
||||
return void event.respondWith(fetch(event.request));
|
||||
}
|
||||
|
||||
// clean the URL, removing any fragment identifier
|
||||
var url = event.request.url.replace(/#.+$/, '');
|
||||
|
||||
// get the init object from Request
|
||||
var init = initFromRequest(event.request)
|
||||
|
||||
// GET requests to our own domain that are *not* #libresilient-info requests
|
||||
// get handled by plugins in case of an error
|
||||
return void event.respondWith(getResourceThroughLibResilient(url, init, clientId))
|
||||
// GET requests to our own domain that are *not* #libresilient-info requests
|
||||
// get handled by plugins in case of an error
|
||||
return getResourceThroughLibResilient(url, init, clientId)
|
||||
}())
|
||||
});
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue