在express4中停止中间件链

时间:2014-07-07 16:10:05

标签: node.js express

下面是添加了中间件功能“checkLogin”的代码。如果用户未登录,eheckLogin中间件应该重定向到登录页面。如果用户登录,它应该呈现所请求的页面。

var express = require('express');
var router = express.Router();
var mongoUri = 'mongodb://localhost/mydb';
var MongoClient = require('mongodb').MongoClient;

function mongoDBConnect(req, res, next) {
    MongoClient.connect('mongodb://localhost/gadda_db', function(err, db) {
    if(!err) {
        req.db = db;
        next();
    } else {
        res.send('unable to connect to mongodb: err = ' + err);
    }
    });
};

function checkLogin(req, res, next) {
    if (req.loggedin) {
    next();
    return;
    }

    if (req.loggedin && req.url === '/login') {
    res.redirect('http://' + 'localhost:3000' + '/game/my_game'); 
    return;
    }

    if (!req.loggedin && req.url === '/login') {
    next();
    return;
    }
    req.db.collection('game_users', function (err, collection) {
        if (err) {
        res.send("error while reading game_users: err " + err);
    }
        collection.findOne({user: req.cookies.user, password: req.cookies.password},
               function (err, user) {
                   if (err) {
                   res.send("error here");
                   return;
                   }
                   req.loggedin = true;
                   next();
                   return;
               });
    });

    res.redirect('login');
    return;
};

router.use(mongoDBConnect);
router.use(checkLogin);

router.get('/', function(req, res) {
    res.redirect('http://' + 'localhost:3000' + '/game/my_game');
});

router.get('/login', function(req, res) {
    res.render('gadda_login', {title: 'gadda', error: ''});
});

当发送对localhost:3000 / gadda的请求时,服务器上会打印以下错误消息

  

GET / gadda / 302 34ms - 66b错误:无法设置标题   发送。       在ServerResponse.OutgoingMessage.setHeader(http.js:691:11)       在ServerResponse.res.set.res.header(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/response.js:551:10)       在ServerResponse.res.send(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/response.js:132:12)       at fn(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/response.js:778:10)       在View.exports.renderFile [作为引擎](/home/hhk/src/nodejs_projects/gadda_v2/node_modules/ejs/lib/ejs.js:318:3)       在View.render(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/view.js:76:8)       在Function.app.render(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/application.js:519:10)       在ServerResponse.res.render(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/response.js:782:7)       在Layer.module.exports [作为句柄](/home/hhk/src/nodejs_projects/gadda_v2/app.js:54:9)       在trim_prefix(/home/hhk/src/nodejs_projects/gadda_v2/node_modules/express/lib/router/index.js:252:17)   router.get / login GET / gadda / login 200 11ms - 546b GET   /stylesheets/style.css 200 4ms - 110b

1 个答案:

答案 0 :(得分:2)

从您上面粘贴的代码中可以看出,您正在重定向到"登录"在等待数据库发现返回之前。尝试将checkLogin函数重构为以下内容:

function checkLogin(req, res, next) {
    if (req.loggedin) {
        if (req.url === '/login') {
            res.redirect('http://' + 'localhost:3000' + '/game/my_game');
            return;
        }
        next();
        return;
    }

    if (!req.loggedin && req.url === '/login') {
        next();
        return;
    }

    req.db.collection('game_users', function(err, collection) {
        if (err) {
            res.send("error while reading game_users: err " + err);
            return;
        }

        collection.findOne({
            user: req.cookies.user,
            password: req.cookies.password
        }, function(err, user) {
            if (err) {
                res.send("error here");
                return;
            }

            if (user) {
                req.loggedin = true;
                next();
                return;
            } else {
                res.redirect('/login');
                return;
            }
        });
    });
}

我已将重定向移至/ login,仅在数据库调用返回时没有匹配的用户时发生。这意味着您已搜索但未找到任何匹配项,这意味着提供的用户和密码(包含在Cookie中?)不正确。

此处的重点是仅执行res.sendres.redirect一次,如果我们在中间件中执行此操作,则只需调用next() 。如果没有致电next(),您的代码就无法点击路线代码。

但请注意,因为此代码不允许任何请求到达目的地,除非它是经过身份验证的请求。这包括favicon或资产等内容。