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('<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:
localhost:3000/classes: logs/:version, directly goeslocalhost:/classes/lastversionnumber; that's unexpectedlocalhost:3000/classes/avalidversionnumber: logs/:version, , goes correct version page; that's normallocalhost:3000/classes/anotvalidversionnumber: logs/:version, , looks class name of not-valid version number, fails, redirect 404 class not found page; that's normallocalhost:3000/classes/anotvalidclassname: log/:version, looks class name, fails, , redirect 404 class not found page; that's normallocalhost:3000/classes/avalidversionnumber/avalidclassname: logs/:version/:classname, goes correct class page; that's normallocalhost: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
Post a Comment