如何修复“ TypeError:app.use()需要中间件功能”?

时间:2019-05-04 03:22:09

标签: javascript node.js express

我是 Node.js 的新手,并且怀疑我的passport.jssignupLogin.js文件中出现错误消息,

  

app.use()需要一个中间件功能

我不知道。我相信这是signupLogin路线,就像我在添加此文件之前一样,该应用程序运行正常。

带有相关文件的我的项目文件夹结构如下:

App
├── config
│   ├── database.js
│   ├── passport.js
├── node_modules
├── public
├── routes
│   ├── index.js
│   ├── product_routes.js
│   ├── signupLogin.js
├── views
├── app.js
├── package-lock.json
├── package.json

signupLogin.js:

var express = require('express');
var router = express.Router();
module.exports = function(router, passport) {
    router.get('/', function(req, res){
     res.render('index.ejs');
    });

    router.get('/login', function(req, res){
     res.render('login.ejs', {message:req.flash('loginMessage')});
    });

    router.post('/login', passport.authenticate('local-login', {
     successRedirect: '/profile',
     failureRedirect: '/login',
     failureFlash: true
    }),
     function(req, res){
      if(req.body.remember){
       req.session.cookie.maxAge = 1000 * 60 * 3;
      }else{
       req.session.cookie.expires = false;
      }
      res.redirect('/');
     });

     router.get('/signup', function(req, res){
     res.render('signup.ejs', {message: req.flash('signupMessage')});
    });

    router.post('/signup', passport.authenticate('local-signup', {
     successRedirect: '/profile',
     failureRedirect: '/signup',
     failureFlash: true
    }));

    router.get('/profile', isLoggedIn, function(req, res){
     res.render('profile.ejs', {
      user:req.user
     });
    });

    router.get('/logout', function(req,res){
     req.logout();
     res.redirect('/');
    })
   };

   function isLoggedIn(req, res, next){
    if(req.isAuthenticated())
     return next();

    res.redirect('/');
   }

app.js:

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var multer = require('multer');
var bodyParser = require('body-parser');
//
var morgan = require('morgan');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
require('./config/passport')(passport);

const app = express();
const PORT = 3000;

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

// Add middleware 
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer({ storage: multer.memoryStorage({}) }).any());
app.use(cookieParser());
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({
 extended: true
}));
app.use(session({
  secret: 'justasecret',
  resave:true,
  saveUninitialized: true
 }));

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



// Tell the app to use the defined routes from above
app.use(require('./routes/index'));
app.use(require('./routes/product_routes'));
app.use(require('./routes/signupLogin.js')(app, passport));


app.listen(PORT, () => {
  console.log(`The app is running on port ${PORT} at 'http://localhost:${PORT}' (Use CTRL + C to exit)`);
});

module.exports = app;

passport.js:

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

var mysql = require('mysql');
var bcrypt = require('bcrypt-nodejs');
var dbconfig = require('./database');
var connection = mysql.createConnection(dbconfig.connection);

connection.query('USE ' + dbconfig.database);

module.exports = function(passport) {
 passport.serializeUser(function(user, done){
  done(null, user.id);
 });

 passport.deserializeUser(function(id, done){
  connection.query("SELECT * FROM users WHERE id = ? ", [id],
   function(err, rows){
    done(err, rows[0]);
   });
 });

 passport.use(
  'local-signup',
  new LocalStrategy({
   usernameField : 'username',
   passwordField: 'password',
   passReqToCallback: true
  },
  function(req, username, password, done){
   connection.query("SELECT * FROM users WHERE username = ? ", 
   [username], function(err, rows){
    if(err)
     return done(err);
    if(rows.length){
     return done(null, false, req.flash('signupMessage', 'That is already taken'));
    }else{
     var newUserMysql = {
      username: username,
      password: bcrypt.hashSync(password, null, null)
     };

     var insertQuery = "INSERT INTO users (username, password) values (?, ?)";
     connection.query(insertQuery, [newUserMysql.username, newUserMysql.password], function(err, rows) {
          if(err) {
            console.log(err);
            return done(null, err);
          } else {
            newUserMysql.id = rows.insertId;
            return done(null, newUserMysql);
        }
     });
    }
   });
  })
 );

 passport.use(
  'local-login',
  new LocalStrategy({
   usernameField : 'username',
   passwordField: 'password',
   passReqToCallback: true
  },
  function(req, username, password, done){
   connection.query("SELECT * FROM users WHERE username = ? ", [username],
   function(err, rows){
    if(err)
     return done(err);
    if(!rows.length){
     return done(null, false, req.flash('loginMessage', 'No User Found'));
    }
    if(!bcrypt.compareSync(password, rows[0].password))
     return done(null, false, req.flash('loginMessage', 'Wrong Password'));

    return done(null, rows[0]);
   });
  })
 );
};

package.json:

{
  "name": "plant-a-tree",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "start http://localhost:3000 & nodemon node app.js"
  },
  "dependencies": {
    "bcrypt-nodejs": "0.0.3",
    "body-parser": "^1.19.0",
    "connect-flash": "^0.1.1",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "ejs": "~2.5.7",
    "express": "~4.16.0",
    "express-session": "^1.16.1",
    "http-errors": "~1.6.2",
    "morgan": "~1.9.0",
    "multer": "^1.4.1",
    "mysql": "^2.17.1",
    "nodemon": "^1.18.11",
    "passport": "^0.4.0",
    "passport-local": "^1.0.0"
  }
}

这是我得到的完整错误:

TypeError: app.use() requires a middleware function
    at Function.use (/Users/charizze/Desktop/PlantATree/node_modules/express/lib/application.js:210:11)
    at Object.<anonymous> (/Users/charizze/Desktop/PlantATree/app.js:47:5)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

2 个答案:

答案 0 :(得分:2)

Express中的

app.use()期望这样的中间件功能:

app.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})

我看到您的中间件功能在signupLogin.js中:

 function isLoggedIn(req, res, next){
    if(req.isAuthenticated())
     return next();
    res.redirect('/');
   }

但是您没有适当地要求它。

app.use(require('./routes/signupLogin.js')(app, passport));

这会加载并执行 signupLogin.js 中的函数,但它不是有效的中间件函数。

我认为您有两个选择。

  1. signupLogin.js 分成2个文件,每个文件仅包含路由,并且不需要 app.use 来使用它,然后创建仅具有中间件功能的另一个文件,然后使用< strong> app.use ,如下所示:
    require('./routes/signupLogin-routes.js')(app, passport)
    app.use(require('./routes/signupLogin-middeware.js'))
  1. 无需 app.use
  2. 即可使用 signupLogin.js
require('./routes/signupLogin.js')(app, passport)

并在 signupLogin.js 中为您的中间件添加 app.use

 app.use(function isLoggedIn(req, res, next){
    if(req.isAuthenticated())
     return next();

    res.redirect('/');
   }
)

答案 1 :(得分:1)

我认为您的问题是与app.js上的路由器导入有关。如错误所示,您需要一个函数来传递app.use()方法,并通过此处的一个路由器。由于您是Node.js的新手,所以我做路由的方法是:

index.js

[...]
const consultas = require("./routes/consultas");
app.use("/api/consultas", consultas);
[...]

/routes/consultas.js

const router = require("express").Router();

router.get("/", (req, res) => {
  // router handle
});

module.exports = router;

我希望这听起来不会太混乱。