Ryan O'D
Ryan O'D

Reputation: 350

Scalable Node Express Routes

I want to set up routes in Node Express to be scalable.

I understand how to set up working routes...it's the failures / mismatches I'm struggling with. More specifically, I am struggling with how to handle 404 errors.

Here is what I have...

app.get('/:folder',function(req,res) {
    var path = 'site/' + req.params.folder + '/index.jade';
    res.render(path);
});

app.get('/:folder/:topic',function(req,res) {
    var path = 'site/' + req.params.folder + '/' + req.params.topic;
    res.render(path);
});

app.use(function(req, res, next){
    res.status(404).render('site/404.jade');
});

The challenge is, :folder and :topic will match to anything so the 404 will never fire. I do not want to hard code all our folder and topic names. So, how do I set up my routing so requests will fall through to the 404 should a folder / topic not exist?

Thanks.

UPDATE

Final, working solution is as follows. Thanks, everyone.

var fs = require('fs');

app.get('/:folder',function(req,res,next) {
    var path = __dirname + '/views/site/' + req.params.folder + '/index.jade';

    if(fs.existsSync(path))
    {
        res.render(path);
    }
    else
    {
        next();
    }
});

app.get('/:folder/:topic',function(req,res,next) {
    var path = __dirname + '/views/site/' + req.params.folder + '/' + req.params.topic + '.jade';

    if(fs.existsSync(path))
    {
        res.render(path);
    }
    else
    {
        next();
    }
});

app.use(function(req, res){
    res.status(404).render('site/404.jade');
});

Upvotes: 2

Views: 486

Answers (3)

vodolaz095
vodolaz095

Reputation: 6986

try

app.get('/:folder/:topic',function(req,res) {
    var path = 'site/' + req.params.folder + '/' + req.params.topic;
    if(fileExists(path)) {
      res.render(path);
    } else {
      res.status(404).render('site/404.jade');        
    }
});

app.get('/:folder',function(req,res) {
    var path = 'site/' + req.params.folder + '/index.jade';
    if(fileExists(path)) {
      res.render(path);
    } else {
      res.status(404).render('site/404.jade');        
    }
});


app.all('*', function(req, res){
    res.status(404).render('site/404.jade');
});

if we has url like /folder/topic, it satisfies route 1, and request is processed. if we has /folder url, it fails to satisfy route 1, but satisfies route 2. if we has something different, than we render path 3.

fileExists is some function to verify, that template exists, http://nodejs.org/api/fs.html#fs_fs_existssync_path for example

Upvotes: 1

Peter Lyons
Peter Lyons

Reputation: 146004

In your folder and topic routes, you need to use fs.exists to see if the view path exists, and if not, just call next() without rendering anything. Then the routing will proceed to the 404 handler.

Upvotes: 2

Mike S
Mike S

Reputation: 42325

There's a third (optional) parameter passed to app.get: next. next is actually a callback that you can call to cause your route to fall through to the next one.

So, you can do something like this:

app.get('/:folder',function(req, res, next) {
    var path = 'site/' + req.params.folder + '/index.jade';
    var pathIsValid = ...  // use something like fs.exists to check if the path is valid
    if (pathIsValid) {
        res.render(path);
    } else {
        next()
    }
});

If next is called, it'll try the next route. If that (and any others) calls next, then you'll get to your 404 handler.

Upvotes: 5

Related Questions