baseprime / grapnel

The smallest JavaScript router with named parameters, HTML5 pushState, and middleware support
http://grapnel.js.org
468 stars 40 forks source link

Middleware support #18

Closed Nicolab closed 9 years ago

Nicolab commented 9 years ago

Hello,

it is possible with Grapnel to make a middleware? Like:

// Middleware
router.get('product/*', function(req, event, next) {
    console.log('middleware called');
  next();
});

// Basic route
router.get('product/:id', function(req, event) {
    console.log('route called');
});
supermensa commented 9 years ago

As I understand this, then the next callback would just call the next route (if any)?

Nicolab commented 9 years ago

Yes like the router of Express (or page.js). It just pass through.

Unless I missed something, currently the only solution is to use the match event and check the req.route.

baseprime commented 9 years ago

Grapnel automatically calls the equivalent of next() unless event.stopPropagation() is called somewhere in the stack. However, the req object is different for route handlers that are called later on. So the concept of middleware is already there.

The solution is simple: allow req to be accessed by other handlers in the stack.


router.get('/profile/*', function(req, e){
    if(user.auth()){
        req.user = user;
    }else{
        e.stopPropagation();
        // Handle
    }
});

router.get('/profile/:username', function(req, e){
    console.log(req.user.id);
});

I like the way that works (above) but it won't work with async, unless you bind to the match event:

router.bind('match', function(e){
    var next = e.callback;

    if(e.route == '/profile/:username'){
        e.preventDefault();
        // Async call
        user.auth(function(err){
            e.params.user = this;
            next();
        });
    }
});

router.get('/profile/:username', function(req, e){
    console.log(req.params.user)
});

Even though the first example won't work with an async call (yet) unless you use the example above, I'll add it to the next release. But I definitely like the idea of eventually enabling routes to modify the req object asynchronously, which effectively allows a route handler to act as middleware.

Nicolab commented 9 years ago

Excellent, thanks. Yes, the first solution is more simple and quick to write.

In passing, thank you for this great router ;)

Nicolab commented 9 years ago

A suggestion, may be coupled with #19 It would be great!

baseprime commented 9 years ago

@Nicolab @supermensa Middleware landed in v0.5.3

Nicolab commented 9 years ago

It's excellent, thanks :)