I am new to Node.js and suspect there is an error in my passport.js or signupLogin.js file with the message,

app.use() requires a middleware function

which I cannot figure out. I believe it's the signupLogin route as before I added this file in, the app was working fine.

My project folder structure with relevant files is as follows:

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"
  }
}

This is the full error I am getting:

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 Answers

2
sensor On Best Solutions

app.use() in express expects a middleware function like so:

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

I see your middleware function is in signupLogin.js:

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

But you are not requiring it properly.

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

This loads and executes the function in signupLogin.js but it is not valid middleware function.

As I see it you have two options.

  1. Split signupLogin.js into 2 files one containing only the routes and require it without app.use and then create another file with only the middleware function and then use app.use like so:
    require('./routes/signupLogin-routes.js')(app, passport)
    app.use(require('./routes/signupLogin-middeware.js'))
  1. require signupLogin.js without app.use
require('./routes/signupLogin.js')(app, passport)

and add app.use in signupLogin.js for your middleware like so:

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

    res.redirect('/');
   }
)
1
Joao Paulo On

I think your problem is with the router import on app.js. As the error says you need a function to pass in the app.use() method, past one of your router here. Since you are new to node.js, the way I do the route is:

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;

I hope this doesn't sound too messy.