我正在研究一個擁有多個路由和子路由的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