Skip to content

Commit

Permalink
Fix route handling of leading, trailing slashes, update workbox to v4
Browse files Browse the repository at this point in the history
  • Loading branch information
humphd committed Apr 3, 2019
1 parent bbf2a8a commit 9263e7c
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 40 deletions.
2 changes: 1 addition & 1 deletion dist/nohost-sw.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/nohost-sw.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if(!('serviceWorker' in navigator)) {
console.log('[nohost] unable to initialize service worker: not supported.');
} else {
navigator.serviceWorker
.register('./nohost-sw.js')
.register('./nohost-sw.js?debug')
.catch(err => {
console.error(`[nohost] unable to register service worker: ${err.message}`);
});
Expand Down
111 changes: 74 additions & 37 deletions src/nohost-sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,86 @@ const jsonFormatter = require('./json-formatter');
const htmlFormatter = require('./html-formatter');
const WebServer = require('./webserver');

/**
* Various features of the server can be configured by passing options on
* the query string when registering the nohost-sw.js service worker file.
*
* `route`: `String` value with the route name to use when listening for filesystem
* path requests. Defaults to `fs`, such that `/fs/path/to/file` would give `/path/to/file`
*
* `disableIndexes`: if present (i.e., `Boolean`), directory indexes will not be shown.
* Users will have to know the filename they wish to get back from the server. Defaults
* to `true` (i.e. directory indexes are shown).
*
* `directoryIndex`: `String` value used to override the default directory index
* used when a filename isn't given. Defautls to `index.html`. For example,
* `/fs/` would return `/fs/index.html` by default, or use another name if
* specified.
*
* `debug`: if present (i.e., `Boolean`), enable workbox debug logging
*/
const config = (function(location) {
const url = new URL(location);

return {
route: url.searchParams.get('route') || 'fs',
disableIndexes: url.searchParams.get('disableIndexes') !== null,
directoryIndex: url.searchParams.get('route') || 'index.html',
debug: url.searchParams.get('debug') !== null
};
}(location));

/* global workbox */
// TODO: include this via package.json
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.6.1/workbox-sw.js');
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.1.1/workbox-sw.js');

workbox.setConfig();
workbox.skipWaiting();
workbox.clientsClaim();
workbox.setConfig({
debug: config.debug,
skipWaiting: true,
clientsClaim: true,
directoryIndex: config.directoryIndex
});

// This will trigger the importScripts() for workbox.strategies and its dependencies
// See workaround in https://developers.google.com/web/tools/workbox/modules/workbox-sw#avoid_async_imports
workbox.loadModule('workbox-strategies');

function debug(msg) {
if(!config.debug) return;
// eslint-disable-next-line no-console
console.log(`[nohost debug] ${msg}`);
}

/**
* Given a route string, make sure it follows the pattern we expect:
* - no escaped characters
* - begins with a `/`
* - ends with a no trailing `/`
*
* If we were passed `'fs'`, we would normalize to `/fs` and
* if we were passed `'first%2Fsecond'`, `'/first/second'`
*
* @param {String} route
*/
function normalizeRoute(route) {
route = decodeURIComponent(route);
// Only a single / at the front of the route
route = route.replace(/^\/*/, '/');
// Only a single / at the end of the route
route = route.replace(/\/*$/, '');

return route;
}

function install(config) {
const route = config.route;
const route = normalizeRoute(config.route);
const webServer = new WebServer(config);
// Route with /path/into/filesystem
const wwwRegex = new RegExp(`/${route}(/.*)`);
// Route with trailing slash (i.e., /path/into/filesystem)
const wwwRegex = new RegExp(`${route}(/.*)`);
// Route minus the trailing slash
const wwwPartialRegex = new RegExp(`/${route}$`);
const wwwPartialRegex = new RegExp(`${route}$`);

debug(`route=${route} wwwRegex=${wwwRegex}`);

workbox.routing.registerRoute(
wwwRegex,
Expand Down Expand Up @@ -44,41 +109,13 @@ function install(config) {
workbox.routing.registerRoute(
wwwPartialRegex,
({ url }) => {
url.pathname = `/${route}/`;
url.pathname = `${route}/`;
return Promise.resolve(Response.redirect(url, 302));
},
'GET'
);
}

/**
* Various features of the server can be configured by passing options on
* the query string when registering the nohost-sw.js service worker file.
*
* `route`: `String` value with the route name to use when listening for filesystem
* path requests. Defaults to `fs`, such that `/fs/path/to/file` would give `/path/to/file`
*
* `disableIndexes`: if present (i.e., `Boolean`), directory indexes will not be shown.
* Users will have to know the filename they wish to get back from the server. Defaults
* to `true` (i.e. directory indexes are shown).
*
* `directoryIndex`: `String` value used to override the default directory index
* used when a filename isn't given. Defautls to `index.html`. For example,
* `/fs/` would return `/fs/index.html` by default, or use another name if
* specified.
*/

function parseConfig(location) {
const url = new URL(location);

return {
route: url.searchParams.get('route') || 'fs',
disableIndexes: url.searchParams.get('disableIndexes') !== null,
directoryIndex: url.searchParams.get('route') || 'index.html'
};
}

self.addEventListener('install', function(event) {
const config = parseConfig(location);
event.waitUntil(Promise.resolve(install(config)));
});

0 comments on commit 9263e7c

Please sign in to comment.