javascript - Express routing: route is ignored -


i'm working on nodejs app possess multiple routes , subroutes, , use express manage them. 1 of feature of app display lists of classes, 1 list of classes per version of software. feature, have 3 subroutes in route 'classes':

var express = require('express'), router = express.router();  var fs = require('fs'); var path = require('path');  router.get('/', function(req, res){     // default route, redirect list of classes of last version of software     // classesgetlastversion(cb) reads json file , launch callback last version number     classesgetlastversion(function(version) {      res.writehead(301, {         location: (req.socket.encrypted ? 'https://' : 'http://') + req.headers.host + '/classes/' + version     });     res.end(); });  router.get('/:version', function(req, res){     // checks given version in argument, display list of classes corresponding      // version (if exists; else: 404 error page)      // retrieve version number specified     var version = req.params.version;      // note: serve static html pages, here directly check if      // corresponding file exists     fs.exists('public/html/classes_' + version + '.html', function(exists){     if(exists){         var options = {             root: path.join(__dirname, __publicrootpath)         };          // file exists, serve         res.status(200);         res.set({'content-type':'text/html'});         res.sendfile('./html/classes_' + version + '.html', options);     } else {         // file doesn't exists, we'll check if req.param.version argument corresponds         // class name, in every version of software          /** file 'data/classes.json' has following architecture:          * {          *      "first_version_number": ["classname1", "classname2", ..., "classnamen"],          *      "second_version_number" : ["classname1", "classname2", ..., "classnamen"],          *      ...          *      "nth_version_number": ["classname1", "classname2", ..., "classnamen"]          * }          **/         fs.readfile('data/classes.json', function(err, data){             if (err) throw err;              // clarification purpose             var classname = version;              var lastversion,                 jsondata = json.parse(data);              for(var versionname in jsondata){                 console.log('searching class in version ' + versionname + '...');                  if(jsondata[versionname].lastindexof(classname) != -1){                     console.log('found it! in v' + versionname);                     lastversion = versionname;                 } else {                     console.log('class not here :-(');                 }             }              if(lastversion){                 // redirect correct class page                 res.writehead(301, {                     location: (req.socket.encrypted ? 'https://' : 'http://') + req.headers.host + '/classes/' + lastversion + '/' + classname                 });                 res.end();             } else {                 // render 404 - page not found                 logger.error('404 error - page not found: public/html/classes_' + version + '.html');                 res.render('errorpages/404.jade', {});             }         });     } });  router.get('/:version/:name', function(req, res){     // check given version , name of class, , display page corresponding     // specified class, if exists; else: 404 error page      var version         = req.params.version;     var classname       = req.params.classname;     classname = classname         .replace('<', '_').replace('>', '_')         .replace('%3ct%3e', '_t_')         .replace('&lt;t$gt;', '_t_');      console.log('/:version/:classname');      var filename = path.join('./public/html/class_' + version, classname) + '.html';     fs.exists(filename, function(exists){         if(!exists){             // 404 class not found             // render 404 - class not found             logger.error('404 error - file not found: '  + filename);             res.render('errorpages/404_class_not_found.jade', {classname:classname});         } else {             filename = path.join('./html/class_' + version, classname) + '.html';              var options = {                 root: path.join(__dirname, __publicrootpath)             };              res.status(200);             res.set({'content-type':'text/html'});             res.sendfile(filename, options);         }     }); });  module.exports = router; 

so, in principle, nothing's tricky , works perfectly, until tried implement new feature: if user tries enter name of class without specifying version, want second route check in json file if class exists in 1 of version of software, , display page corresponding class in last version found.

but thing is, unknown reason, when try access /classes/nameofaclass, doesn't evaluate second route, unless enter complete bullshit name of class. if give name of correct class, goes in third route (even if give one parameter), , gives last version number of software :version parameter, , tries resolve /classes/lastversion/nameoftheclass.

do have idea why ignores second route 1 parameter , goes directly third route, giving automatically valid version number?

edited -> more code now

to me, here's additional infos app: @ root of projet, have file server.js, declares:

var app = require('./app'); 

inside app.js file, have:

var express  = require('express'); var app      = express();  app.use(compress());  // serve static files (css, js, images) app.use(express.static('public')); app.set('view engine', 'jade'); app.set('views', './views'); app.set('view cache', true);  //require routes, index.js called default require('./scripts/router')(app);  module.exports = app; 

before ask "why heck did that": architecture (server file require app file declares express app) needed on platform i'll have deploy app on. let's continue further in architecture.

you surely have notices line require('./scripts/router')(app);. in router folder, have single file called "index.js" , folder named "routes"; folder contains subroutes. index.js file follow:

module.exports = function (app) {     // require several subroutes follow     app.use('/classes', require('./routes/classes'));     [...other subroutes...]      // errors     // handle 404     app.use(function (error, req) {         req.status(404);         req.render('errorpages/404.jade', {});     });      // handle 500     app.use(function (error, req, res, next) {         res.status(500);         res.render('errorpages/500.jade', {});     }); }; 

so, in resume:

myprojectroot |_ server.js |_ app.js |_ scripts/     |_ router/         |_ index.js         |_ routes/             |_ classes.js             |_ otherroute.js             |_ etc... 

hope that's helping understand problem :-)

new info

hey! did think problem strange? got stranger! user kanzelm suggested, console.logged (meaning: @ beginning of each route, console.log('nameoftheroute');), , results totally unexpected:

  1. localhost:3000/classes: logs /:version , directly goes localhost:/classes/lastversionnumber; that's unexpected
  2. localhost:3000/classes/avalidversionnumber: logs /:version, , goes correct version page; that's normal
  3. localhost:3000/classes/anotvalidversionnumber: logs /:version, , looks class name of not-valid version number, fails, redirect 404 class not found page; that's normal
  4. localhost:3000/classes/anotvalidclassname: log /:version, looks class name, fails, , redirect 404 class not found page; that's normal
  5. localhost:3000/classes/avalidversionnumber/avalidclassname: logs /:version/:classname , goes correct class page; that's normal
  6. localhost:3000/classes/avalidversionnumber/anotvalidclassname: logs /:version/:classname , goes 404 class not found page; that's normal

so, here have 2 major problems can't understand: first, the root route totally ignored , never catched, when try go locahost:3000/classes; seems url auto-completed last valid version number. in theory, that's want (look @ code of first route), no console.log route, neither method classesgetlastversion, shown. secondly, fact route /:version catched when valid version number given (which totally fine) or when non-valid version number/class name given (which totally not ok @ all) driving me mad.

any idea?

my hunch block of code being executed , falling "lastverison":

        if(lastversion){             // redirect correct class page             res.writehead(301, {                 location: (req.socket.encrypted ? 'https://' : 'http://') + req.headers.host + '/classes/' + lastversion + '/' + classname             });             res.end();         } 

try logging "exists" , seeing if that's true or false.


Comments