diff --git a/__tests__/config.json b/__tests__/config.json index 87dec51..639abb8 100644 --- a/__tests__/config.json +++ b/__tests__/config.json @@ -1,16 +1,13 @@ { "plugins": [{ - "name": "fetch" - },{ - "name": "cache" - },{ "name": "basic-integrity", - "integrity": [{ - "/test.json": "sha384-kn5dhxz4RpBmx7xC7Dmq2N43PclV9U/niyh+4Km7oz5W0FaWdz3Op+3K0Qxz8y3z" - }], + "requireIntegrity": false, + "integrity": { + "http://localhost:8000/__tests__/test.json": "sha256-FCNALvZ0mSxEs0+SjOgx/sDFFVuh0MwkhhYnI0UJWDg=" + }, "uses": [{ "name": "fetch" }] }], - "loggedComponents": ["service-worker", "fetch", "cache"] + "loggedComponents": ["service-worker", "fetch", "cache", "basic-integrity"] } diff --git a/service-worker.js b/service-worker.js index 1e4ba57..04f4ef1 100644 --- a/service-worker.js +++ b/service-worker.js @@ -83,12 +83,35 @@ if (typeof self.LibResilientConfig !== 'object' || self.LibResilientConfig === n * items - the rest of arguments will be passed to console.debug() */ self.log = function(component, ...items) { - if (self.LibResilientConfig.loggedComponents.indexOf(component) >= 0) { - console.debug(`LibResilient [COMMIT_UNKNOWN, ${component}] ::`, ...items) + if ( ('LibResilientConfig' in self) && ('loggedComponents' in self.LibResilientConfig) && (self.LibResilientConfig.loggedComponents != undefined)) { + if (self.LibResilientConfig.loggedComponents.indexOf(component) >= 0) { + console.debug(`LibResilient [COMMIT_UNKNOWN, ${component}] ::`, ...items) + } } } +/** + * verifying a config JSON + * + * cdata - config data to verify + */ +let verifyConfigData = (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') + return false; + } + // basic check for the loggedComponents + if ( !("loggedComponents" in cdata) || !Array.isArray(cdata.loggedComponents) ) { + self.log('service-worker', 'fetched config does not contain a valid "loggedComponents" field') + return false; + } + // we're good + return true; +} + + // load the plugins // // everything in a try-catch block @@ -103,14 +126,17 @@ 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? - console.debug('* * * LOADING CONFIG * * *') try { //self.importScripts(self.registration.scope + "config.json") var cdata = await fetch(self.registration.scope + "config.json") cdata = await cdata.json() - self.LibResilientConfig.plugins = cdata.plugins - self.LibResilientConfig.loggedComponents = cdata.loggedComponents - self.log('service-worker', 'config loaded.') + if (verifyConfigData(cdata)) { + self.LibResilientConfig.plugins = cdata.plugins + self.LibResilientConfig.loggedComponents = cdata.loggedComponents + self.log('service-worker', 'config loaded.') + } else { + self.log('service-worker', 'ignoring invalid config, using defaults.') + } } catch (e) { self.log('service-worker', 'config loading failed, using defaults') } @@ -446,7 +472,6 @@ let initFromRequest = (req) => { * reqInfo - instance of LibResilientResourceInfo */ let libresilientFetch = (plugin, url, init, reqInfo) => { - // status of the plugin reqInfo.update({ method: plugin.name, @@ -494,19 +519,14 @@ let callOnLibResilientPlugin = (call, args) => { * and returns a Promise resolving to a Response in case any of the plugins * was able to get the resource * - * request - string containing the URL we want to fetch + * url - the url we want to fetch + * init - the init data for responses * clientId - string containing the clientId of the requesting client * useStashed - use stashed resources; if false, only pull resources from live sources * doStash - stash resources once fetched successfully; if false, do not stash pulled resources automagically * stashedResponse - TBD */ -let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStash=true, stashedResponse=null) => { - - // clean the URL, removing any fragment identifier - var url = request.url.replace(/#.+$/, ''); - - // get the init object from Request - var init = initFromRequest(request) +let getResourceThroughLibResilient = (url, init, clientId, useStashed=true, doStash=true, stashedResponse=null) => { // set-up reqInfo for the fetch event var reqInfo = new LibResilientResourceInfo(url, clientId) @@ -576,8 +596,7 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas self.log('service-worker', 'starting background no-stashed fetch for:', url); // event.waitUntil? // https://stackoverflow.com/questions/37902441/what-does-event-waituntil-do-in-service-worker-and-why-is-it-needed/37906330#37906330 - // TODO: perhaps don't use the `request` again? some wrapper? - getResourceThroughLibResilient(request, clientId, false, true, response.clone()).catch((e)=>{ + getResourceThroughLibResilient(url, init, clientId, false, true, response.clone()).catch((e)=>{ self.log('service-worker', 'background no-stashed fetch failed for:', url); }) // return the response so that stuff can keep happening @@ -678,7 +697,6 @@ let getResourceThroughLibResilient = (request, clientId, useStashed=true, doStas /* ========================================================================= *\ |* === Setting up the event handlers === *| \* ========================================================================= */ - self.addEventListener('install', async (event) => { event.waitUntil(initServiceWorker()) // TODO: Might we want to have a local cache? @@ -746,10 +764,16 @@ self.addEventListener('fetch', event => { 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(event.request, clientId)) + return void event.respondWith(getResourceThroughLibResilient(url, init, clientId)) });