Resolving overlapping routes

674 views
Skip to first unread message

Laurie Harper

unread,
Feb 13, 2011, 2:31:20 AM2/13/11
to expre...@googlegroups.com
I'm having a little trouble with Express/Connect and the way the router middleware normalizes route paths. I'm trying to create a set of routes that look like this:

app.get('/blog', loadEntries);
app.get('/blog', showEntries);
app.put('/blog', createEntry);
app.get('/blog/new', createEntryForm);

app.get('/blog/:title', loadEntry);
app.get('/blog/:title', showEntry);

The problem is, a request for /blog/new matches both the "/blog/new" and "/blog/:title" routes. Ithought I'd be able to resolve the conflict like this:

app.get('/blog/_new', createEntryForm);
app.get('/blog/:title([^_].*)', loadEntry);
...

However, that doesn't work; the capture pattern is normalized, resulting in a route that matches with this regex:

^\/blog\/(?:([^_](.+)))\/?$

i.e. "/blog/" followed by a literal "." followed by one or more characters... Removing the "." from the pattern doesn't fully fix things, either, because that (.+) term is introducing an additional capture group.

I can live with dropping the ".", but that extra capture group really looks like a bug to me... Is it intentional? If not, I'l send a pull request with a fix and move on ;-) If it is, how do I set up a route in such a way that usurps other routes that would match?

Hope that makes sense...
--
Laurie Harper
http://laurie.holoweb.net/

vision media [ Tj Holowaychuk ]

unread,
Feb 14, 2011, 11:29:52 AM2/14/11
to expre...@googlegroups.com
this works completely as expected to me:


/**
 * Module dependencies.
 */

var express = require('express');

var app = express.createServer();

app.get('/blog/new', function(req, res, next){
  res.send('new blog post');
});

app.get('/blog/:title', function(req, res, next){
  res.send('blog post ' + req.params.title);
});

app.listen(3000);




--
You received this message because you are subscribed to the Google Groups "Express" group.
To post to this group, send email to expre...@googlegroups.com.
To unsubscribe from this group, send email to express-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/express-js?hl=en.




--
Tj Holowaychuk
Vision Media
President & Creative Lead

Laurie Harper

unread,
Feb 14, 2011, 12:21:17 PM2/14/11
to expre...@googlegroups.com
Hmm, I tried it and, sure enough, it worked as intended. Reversing the order of the routes results in the /blog/new route not firing, though -- which turns out to be my problem. When I wrote out the example in the first post I listed the routes in a different order than I was actually using. I reordered the routes in my actual code and, hey presto, I get the behaviour I was looking for! :-)

Thanks for the sanity check; I'm not sure *why* this works, but I'm happy it does ;-)

L.
-- 
Laurie Harper



vision media [ Tj Holowaychuk ]

unread,
Feb 14, 2011, 12:25:57 PM2/14/11
to expre...@googlegroups.com
ah :)

well, it makes sense, since the routes defined first take precedence:

/foo/:bar
/foo/new

in this example /foo/:bar would always consume /foo/new etc. maybe some day express will perform lookaheads to see if any other routes could satisfy more directly, but not likely

Laurie Harper

unread,
Feb 14, 2011, 12:30:43 PM2/14/11
to expre...@googlegroups.com
Doh! Click! Just realized where my confusion was coming from: I have data-fetch routes which call next(), and page render routes which call res.render(). I was confused as to why some routes were firing more than one handler, and some weren't -- which is because that's what I was telling them to do in the handlers... sheesh. OK, now everything is making sense again :)

L.
Reply all
Reply to author
Forward
0 new messages