[英]Node.js with exress handle database connection error outside middleware
我對node還是很陌生,我正在嘗試使用passportjs創建一個簡單的登錄/注冊系統。 我有我的護照配置文件,在其中我將護照對象作為參數傳遞,如下所示。
我的護照配置文件:
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服務器由於任何原因而關閉,則該錯誤會引發在我的第一行中。 我希望能夠將用戶重定向到一個簡單的頁面,該頁面向他顯示諸如“數據庫有問題,請稍后再試”。 問題是,當我拋出錯誤時,我的應用程序會立即關閉,並向任何訪問者提供ERR_CONNECTION_REFUSED響應。(我目前正在本地進行此操作。
這是我的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;
話雖如此,由於錯誤是在我的password-config文件中引發的,它沒有遵循具有req,res和next params的中間件約定,我如何才能將用戶正確地重定向到上述頁面?
可以肯定的是,我會再說一遍,這僅涉及mysql連接錯誤。 我知道我可以使用done()通過我的password-config方法返回其他錯誤,但是數據庫連接錯誤發生在具有完成參數的函數外部。
提前致謝
經過仔細研究后,我想到的唯一解決方法似乎是將查詢合並到通行證配置方法中,以便我可以通過done()函數將任何數據庫連接錯誤傳回。
這是我修改過的護照配置文件
// 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
}
});
});
});
}
));
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.