我正在研究一个拥有多个路由和子路由的NodeJS应用,并使用Express来管理它们。我的应用程序的一个特点是显示类的列表,每个软件版本的一个类列表。针对这一特点,我对路线“类”三子路径:高速路由:路由被忽略
var express = require('express'),
router = express.Router();
var fs = require('fs');
var path = require('path');
router.get('/', function(req, res){
// default route, redirect to the list of classes of the last version of the software
// classesGetLastVersion(cb) reads a JSON file and launch callback with 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 the given version in argument, display the list of classes corresponding
// to the version (if it exists; else: 404 error page)
// retrieve the version number specified
var version = req.params.version;
// NOTE: we only serve static HTML pages, so here I directly check if the
// corresponding file exists
fs.exists('public/html/classes_' + version + '.html', function(exists){
if(exists){
var options = {
root: path.join(__dirname, __publicRootPath)
};
// file exists, serve it
res.status(200);
res.set({'Content-type':'text/html'});
res.sendFile('./html/classes_' + version + '.html', options);
} else {
// file doesn't exists, so we'll check if the req.param.version argument corresponds
// to a class name, in every version of the software
/** the file 'data/classes.json' has the 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;
// for 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 is not here :-(');
}
}
if(lastVersion){
// redirect to the 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 the given version AND name of the class, and display the page corresponding
// to the specified class, if it 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;
因此,在原则上,没有什么是棘手的,一切完美,直到我试图执行一个新的功能:如果用户试图进入没有指定其版本的类的名称,我希望第二个路由检查JSON文件,如果该类存在于某个版本的软件中,并显示与找到的最新版本中类相对应的页面。
但是,由于不明原因,当我尝试访问/ classes/nameOfAClass时,它不会评估第二条路线,除非我为该类的名称输入完整的废话。如果我给出一个正确的类的名称,它立即在第三个路由(即使我只给它一个参数),并给出:version
参数的软件的最新版本号,并尝试resolve/classes/lastVersion/nameOfTheClass。
你有什么想法,为什么它只是忽略只有一个参数的第二条路线,直接进入第三条路线,自动给出一个有效的版本号?
EDITED - >更多的代码,现在
为了帮助你帮我,这里是关于应用中的一些附加的相关信息: 在我谟的根,我有一个文件server.js,它声明:
var app = require('./app');
app.js文件里面,我有:
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 all routes, index.js is called by default
require('./scripts/router')(app);
module.exports = app;
你会问自己“为什么之前到底他做那个“:该平台需要架构(需要自己声明快速应用的应用文件的服务器文件),我将不得不部署我的应用。让我们继续进一步的体系结构。
您当然有注意行require('./scripts/router')(app);
。在这个路由器文件夹中,我有一个名为“index.js”的文件和一个名为“routes”的文件夹;这个文件夹包含我所有的子路由。该index.js文件如下:
module.exports = function (app) {
// require several subroutes as 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', {});
});
};
所以,在简历:
myProjectRooT
|_ server.js
|_ app.js
|_ scripts/
|_ router/
|_ index.js
|_ routes/
|_ classes.js
|_ otherRoute.js
|_ etc...
希望这有助于理解这个问题:-)
最新资讯
嘿!你认为这个问题很奇怪吗?它变得更加陌生!正如用户kanzelm建议的那样,我使用控制台。记录一切(意思是:在每条路线的开始,我做console.log('nameOfTheRoute');
),以及一些研究结果完全出乎意料:
localhost:3000/classes
:原木/:version
,并直接进入localhost:/classes/lastVersionNumber
; 这真的出乎意料localhost:3000/classes/aValidVersionNumber
:日志/:version
,并转到正确的版本页面;这很正常localhost:3000/classes/aNotValidVersionNumber
:日志/:version
,并查找一个名称为无效版本号的类,失败,然后重定向到404类未找到的页面;这是正常的localhost:3000/classes/aNotValidClassName
:log/:version
,查找与此名称的类,失败,并重定向到404类未找到页面;这是正常的localhost:3000/classes/aValidVersionNumber/aValidClassName
:日志/:version/:className
并转到正确的类页面;这是正常的localhost:3000/classes/aValidVersionNumber/aNotValidClassName
:日志/:version/:className
并转到404类未找到的页面;这是正常的
所以,在这里我有两个主要问题我甚至无法理解:第一,根路径是完全忽略,总是擦肩而过,甚至当我尝试去locahost:3000/classes
;它似乎是自动完成与最后一个有效的版本号。理论上,这就是我想要的(查看第一条路线的代码),但没有显示路线中的console.log,也没有显示方法classesGetLastVersion
。其次,仅当给出有效版本号(完全正常)或给出无效版本号/类名称(根本不完全没有问题)时才会捕获路由/:version
这一事实,这使得我疯狂。
有什么想法?
恐怕我们在这里缺乏一些信息。只用这个代码,我们无法猜测为什么一个有效的魔法版本号从野外出现。也许你使用一些URL重写工具? (阿帕奇也许?) – Magus
我会编辑第一篇文章,向您展示路由中的一些代码;-)因此,我不知道你在说什么(url重写工具),所以我想我没有使用它,除非意外: -/ – TheFrenchieCake
你错过了'});'关闭'classesGetLastVersion('在你的第一条路线 – Plato