Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a single fetch handler per Router #382

Merged
merged 3 commits into from
Mar 25, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 78 additions & 69 deletions packages/sw-routing/src/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,68 +50,17 @@ import logHelper from '../../../../lib/log-helper.js';
*/
class Router {
/**
* An optional default handler will have its handle method called when a
* request doesn't have a matching route.
*
* @example
* router.setDefaultHandler({
* handler: new goog.runtimeCaching.NetworkFirst()
* });
*
* @param {Object} input
* @param {Object} input.handler An Object with a `handle` method.
*/
setDefaultHandler({handler} = {}) {
assert.hasMethod({handler}, 'handle');

this.defaultHandler = handler;
}

/**
* If a Route throws an error while handling a request, this catch handler
* will be called to return an error case.
*
* @example
* router.setCatchHandler({
* handler: ({event, params}) => {
* return caches.match('/error-page.html');
* }
* });
*
* @param {Object} input
* @param {Object} input.handler An Object with a `handle` method.
* Start with an empty array of routes, and set up the fetch handler.
*/
setCatchHandler({handler} = {}) {
assert.hasMethod({handler}, 'handle');

this.catchHandler = handler;
}

/**
* Register routes will take an array of Routes to register with the
* router.
*
* @example
* router.registerRoutes({
* routes: [
* new RegExpRoute({ ... }),
* new ExpressRoute({ ... }),
* new Route({ ... }),
* ]
* });
*
* @param {Object} input
* @param {Array.<Route>} input.routes An array of routes to register.
*/
registerRoutes({routes} = {}) {
assert.isArrayOfClass({routes}, Route);
constructor() {
this._routes = [];

self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (!url.protocol.startsWith('http')) {
logHelper.log({
that: this,
message: 'URL does not start with HTTP and so not parsing ' +
message: 'URL does not start with HTTP and so not passing ' +
'through the router.',
data: {
request: event.request,
Expand All @@ -122,7 +71,7 @@ class Router {

let responsePromise;
let matchingRoute;
for (let route of (routes || [])) {
for (let route of this._routes) {
if (route.method !== event.request.method) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we drop support for 'all' like sw-toolbox had?

If so, should we group routes together by method - reducing this loop for each request?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we don't have support for all. I can switch to keeping track of routes per-method to optimize the loop.

continue;
}
Expand Down Expand Up @@ -169,23 +118,83 @@ class Router {

if (responsePromise) {
event.respondWith(responsePromise
.then((response) => {
logHelper.debug({
that: this,
message: 'The router is managing a route with a response.',
data: {
route: matchingRoute,
request: event.request,
response: response,
},
});

return response;
}));
.then((response) => {
logHelper.debug({
that: this,
message: 'The router is managing a route with a response.',
data: {
route: matchingRoute,
request: event.request,
response: response,
},
});

return response;
}));
}
});
}

/**
* An optional default handler will have its handle method called when a
* request doesn't have a matching route.
*
* @example
* router.setDefaultHandler({
* handler: new goog.runtimeCaching.NetworkFirst()
* });
*
* @param {Object} input
* @param {Object} input.handler An Object with a `handle` method.
*/
setDefaultHandler({handler} = {}) {
assert.hasMethod({handler}, 'handle');

this.defaultHandler = handler;
}

/**
* If a Route throws an error while handling a request, this catch handler
* will be called to return an error case.
*
* @example
* router.setCatchHandler({
* handler: ({event, params}) => {
* return caches.match('/error-page.html');
* }
* });
*
* @param {Object} input
* @param {Object} input.handler An Object with a `handle` method.
*/
setCatchHandler({handler} = {}) {
assert.hasMethod({handler}, 'handle');

this.catchHandler = handler;
}

/**
* Register routes will take an array of Routes to register with the
* router.
*
* @example
* router.registerRoutes({
* routes: [
* new RegExpRoute({ ... }),
* new ExpressRoute({ ... }),
* new Route({ ... }),
* ]
* });
*
* @param {Object} input
* @param {Array.<Route>} input.routes An array of routes to register.
*/
registerRoutes({routes} = {}) {
assert.isArrayOfClass({routes}, Route);
// Give precedence to the newly registered routes by listing them first.
this._routes = routes.concat(this._routes);
}

/**
* Registers a single route with the router.
*
Expand Down