page.js icon indicating copy to clipboard operation
page.js copied to clipboard

No way to handle 404 with indeterminate execution order

Open em opened this issue 11 years ago • 5 comments
trafficstars

I'm using page.js in an environment where I load individual components that set up their routes in an indeterminate order, for performance reasons.

This doesn't cause any problems with router handler precedence because I simply make the URIs not conflict.

However that is not a solution for 404 handling. I need a solution that would allow me to handle 404s without depending on it being the last route added.

Ideally there would be some support for precedence that does not rely on execution order.

Another simpler way, would be to give route handler the ability to determine if there are any subsequent matches to the route.

For instance, if next() returned true when a handler was called, or false on unhandled, I could do this at any place in my code without caring about order:

page('*', function(ctx, next) {
  if(!next()) {
     // handle 404
  }
}); 

I see this as a side effect of carrying over the server-side express routing style into the browser, where you can not rely on the same assumptions about dependency execution order.

em avatar Sep 24 '14 02:09 em

+1 - This is exactly what I need as well. My case is slightly different in that protected routes are not added until we verify the users authentication, which is async and long after we've registered the 404 handler.

evanworley avatar Oct 30 '14 23:10 evanworley

@em you can use hack with setTimeout as workaround:

setTimeout(function () {
  page(function (ctx) {
    // handle 404
  });
  page.start();
}, 0);

It's weird and it should work only if all your middlewares are defined synchronously. Now I have no idea to implement 404 because:

  • all unhandled routes should be redirected to they url
  • implementation should respect existing API

mb server side 404 can help you?

A avatar Nov 04 '14 22:11 A

I think the right solution would be to define a match score on the pattern, similar to how CSS selector specificity and order works. The * selector should have a match score of 0, so it would only trigger if no other pattern matched, regardless of when it was registered. Not sure how route matching works today. How does the system decide between /user and /user/:username when someone visits /user/foo?

evanworley avatar Nov 05 '14 19:11 evanworley

what about middlewares that just extend ctx for others like plugins?

A avatar Nov 05 '14 22:11 A

I think we could maybe document how to do this sort of thing with middleware.

matthewp avatar Jan 14 '18 18:01 matthewp