node.js带有exress handle数据库连接错误中间件外部

vof42yt1  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(257)

我对node还比较陌生,我正在尝试用passportjs创建一个简单的登录/注册系统。我有一个passport配置文件,在其中我将passport对象作为一个参数传递,如下所示。
我的passport配置文件:

var LocalStrategy   = require('passport-local').Strategy;

var User = require('./../models/user');

var mysql = require('./../database/mysql_setup');
var mysqlPool = mysql.pool;

// expose this function to our app using module.exports
module.exports = function(passport) {

    mysqlPool.getConnection(function(error, connection) {

        if (error) throw error;

        connection.query('USE vidyawxx_build2');

        // =========================================================================
        // passport session setup ==================================================
        // =========================================================================
        // required for persistent login sessions
        // passport needs ability to serialize and deserialize users out of session

        // used to serialize the user for the session
        passport.serializeUser(function(user, done) {
            done(null, user.username);
        });

        // used to deserialize the user
        passport.deserializeUser(function(username, done) {
            connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE username = " + connection.escape(username), function(err,rows){
                done(err, rows[0]);
            });
        });

        // =========================================================================
        // LOCAL SIGNUP ============================================================
        // =========================================================================
        // we are using named strategies since we have one for login and one for signup
        // by default, if there was no name, it would just be called 'local'

        passport.use('local-signup', new LocalStrategy({
                // by default, local strategy uses username and password, we will override with email
                usernameField : 'username',
                passwordField : 'password',
                passReqToCallback : true // allows us to pass back the entire request to the callback
            },
            function(req, username, password, done) {

                // find a user whose username is the same as the forms username
                // we are checking to see if the user trying to login already exists
                connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE `username` = "+connection.escape(username),function(err,rows){
                    if (err)
                        return done(err);
                    if (rows.length) {
                        return done(null, false, req.flash('error', 'This username is already in use.'));
                    } else {

                        // if there is no user with that username
                        // create the user
                        var newUserMysql = new User(username, password);

                        newUserMysql.generateHash(function(error, hash) {

                            if(error) {
                                return done(error);
                            }

                            var insertQuery = "INSERT INTO `"+mysql.dbSpecs.prefix+"users` ( username, password ) values (" + connection.escape(newUserMysql.username) +",'"+ hash +"')";

                            connection.query(insertQuery,function(err,rows){
                                if(err) {
                                    return done(error);
                                }
                                return done(null, rows);
                            });

                        });

                    }
                });
            }
        ));

        // =========================================================================
        // LOCAL LOGIN =============================================================
        // =========================================================================
        // we are using named strategies since we have one for login and one for signup
        // by default, if there was no name, it would just be called 'local'

        passport.use('local-login', new LocalStrategy({
                // by default, local strategy uses username and password
                usernameField : 'username',
                passwordField : 'password',
                passReqToCallback : true // allows us to pass back the entire request to the callback
            },
            function(req, username, password, done) { // callback with email and password from our form

                connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE `username` = " + connection.escape(username), function(err,rows){

                    if (err) {
                        return done(err);
                    }
                    if (rows.length === 0) {
                        return done(null, false, req.flash('error', 'Oops! Wrong username or password.')); // req.flash is the way to set flashdata using connect-flash
                    }

                    // if the user is found but the password is wrong
                    var newUser = new User(username, password);
                    newUser.compareHash(function(error, result) {
                        if(result) {
                            return done(null, rows[0]);
                        } else {
                            return done(null, false, req.flash('error', 'Oops! Wrong username or password.')); // create the loginMessage and save it to session as flashdata
                        }
                    });

                });

            }
        ));

        connection.release();

    });
};

我的问题在于,如果我的mysql服务器由于任何原因而关闭,那么错误就会被抛出到我的第一行。我希望能够重定向到一个简单的页面,给他一个信息,如“数据库有问题,请稍后再试”。问题是,当我抛出错误时,我的应用程序只是关闭了,给任何访问者错误连接拒绝的响应。
这是我的app.js文件:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var passport = require('passport');
var passportConfig = require('./config/passport');

var session = require("express-session");
var flash = require("connect-flash");

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();
app.use(express.static(path.join(__dirname, 'public')));

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

passportConfig(passport);
app.use(session({
    secret: "aPa1fgOed(&fjkKLN34%#$lpv@@",
    resave: true,
    saveUninitialized: true,
    cookie: { maxAge: 1000*60*15 } //15 minutes in milliseconds
}));

app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

//create local vaariables for all our templates to use
app.use(function(req, res, next) {
    res.locals.errors = req.flash("error");
    res.locals.infos = req.flash("info");
    res.locals.successes = req.flash("success");
    next();
});

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

这就是说,由于错误是在我的passport配置文件中抛出的,它不遵循具有req、res和next参数的中间件约定,因此如何将用户重定向到上面提到的页面?
当然,我要再说一遍,这只涉及mysql连接错误。我知道我可以使用done()通过passport config方法返回其他错误,但是数据库连接错误发生在具有done参数的函数之外。
提前谢谢

klsxnrf1

klsxnrf11#

看起来在仔细研究之后,我能想到的唯一解决方法是将查询合并到passport配置方法中,这样我就可以通过done()函数传回任何数据库连接错误;
这是我修改过的passport配置文件

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;

var User = require('./../models/user');

var mysql = require('./../database/mysql_setup');
var mysqlPool = mysql.pool;

// expose this function to our app using module.exports
module.exports = function(passport) {

    //connection.query('USE vidyawxx_build2');

    // =========================================================================
    // passport session setup ==================================================
    // =========================================================================
    // required for persistent login sessions
    // passport needs ability to serialize and deserialize users out of session

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.username);
    });

    // used to deserialize the user
    passport.deserializeUser(function(username, done) {
        mysqlPool.getConnection(function(dbError, connection) {

            if(dbError) {
                return done(dbError);
            }

            connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE username = " + connection.escape(username), function(err,rows){
                if(err) {
                    done(err);
                    connection.release();
                    return;
                }
                connection.release();
                done(err, rows[0]);
            });
        });
    });

    // =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-signup', new LocalStrategy({
            // by default, local strategy uses username and password, we will override with email
            usernameField : 'username',
            passwordField : 'password',
            passReqToCallback : true // allows us to pass back the entire request to the callback
        },
        function(req, username, password, done) {

            // find a user whose username is the same as the forms username
            // we are checking to see if the user trying to login already exists
            mysqlPool.getConnection(function(dbError, connection) {

                if(dbError) {
                    return done(dbError);
                }

                connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE `username` = "+connection.escape(username),function(err,rows){

                    if (err) {
                        connection.release();
                        return done(err);
                    }

                    if (rows.length) {
                        connection.release();
                        return done(null, false, req.flash('error', 'This username is already in use.'));
                    } else {

                        // if there is no user with that username
                        // create the user
                        var newUserMysql = new User(username, password);

                        newUserMysql.generateHash(function(error, hash) {

                            if(error) {
                                connection.release();
                                return done(error);
                            }

                            var insertQuery = "INSERT INTO `"+mysql.dbSpecs.prefix+"users` ( username, password ) values (" + connection.escape(newUserMysql.username) +",'"+ hash +"')";

                            mysqlPool.query(insertQuery,function(err,rows){
                                if(err) {
                                    connection.release();
                                    return done(error);
                                }
                                connection.release();
                                return done(null, rows);
                            });

                        });

                    }
                    connection.release();
                });

            });
        }
    ));

    // =========================================================================
    // LOCAL LOGIN =============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-login', new LocalStrategy({
            // by default, local strategy uses username and password
            usernameField : 'username',
            passwordField : 'password',
            passReqToCallback : true // allows us to pass back the entire request to the callback
        },
        function(req, username, password, done) { // callback with email and password from our form

            mysqlPool.getConnection(function(dbError, connection) {
                if(dbError) {
                    return done(dbError);
                }
                connection.query("SELECT * FROM `"+mysql.dbSpecs.prefix+"users` WHERE `username` = " + connection.escape(username), function(err,rows){

                    if (err) {
                        connection.release();
                        return done(err);
                    }
                    if (rows.length === 0) {
                        connection.release();
                        return done(null, false, req.flash('error', 'Oops! Wrong username or password.')); // req.flash is the way to set flashdata using connect-flash
                    }

                    // if the user is found but the password is wrong
                    var newUser = new User(username, password);
                    newUser.compareHash(function(error, result) {
                        if(result) {
                            connection.release();
                            return done(null, rows[0]);
                        } else {
                            connection.release();
                            return done(null, false, req.flash('error', 'Oops! Wrong username or password.')); // create the loginMessage and save it to session as flashdata
                        }
                    });

                });
            });
        }
    ));

};

相关问题