Error in node.js/express app: Can't set headers after they are sent

I have a problem with setting up a Node.js application with Express for routing and MongoDB (Mongolab) for the database. I've been looking around & found a lot of other users with the same problem, but couldn't find a solution for the problem yet.. Hope that someone can help.

The error I keep getting is Error: Can't set headers after they are sent.

I get the error after a POST /login request. I've tried to use res.end();, res.redirect('/users/index'); and to return the render.. But no success yet..

Here the most important code:

Server.js

  /* LOAD ALL DEPENDENCIES
    ----------------------------------------- */
    const express = require('express');
    const path = require('path');
    const request = require('request');
    const session = require('express-session');
    const compression = require('compression');
    const bodyParser = require('body-parser');
    const app = express();

    /* MONGODB CONFIGURATION
    ----------------------------------------- */
    const MongoClient = require("mongodb").MongoClient;
    require('dotenv').config();
    const dbConfig = process.env.MONGODB_URI;

    MongoClient.connect(dbConfig, (err, database) => {
      if (err) return console.log(err)
      db = database
    });

    /* SESSIONS CONFIGURATION
    ----------------------------------------- */
    app.use(session({
        secret: "JA1d82JHYF9?nsdfDF635MuHe#ksd",
        resave: false,
        saveUninitialized: true
    }));

    /* SET PORT FOR HEROKU
    ----------------------------------------- */
    const port = process.env.PORT || 3000;
    const host = process.env.HOST ||'0.0.0.0';

    // Rest of the code ..

    app.use('/users', usersRouter);
    // Router is loaded earlier

    /* START THE NPM SERVER
    ----------------------------------------- */
    app.listen(port, host, function() {
        console.log(`Server started on port ${port}`);
    });

users.js (route)

/* LOAD ALL DEPENDENCIES
----------------------------------------- */
const express = require('express');
const router = express.Router();
const passwordHash = require('password-hash');

/* INDEX ROUTE
----------------------------------------- */
router.get('/', function(req, res) {
  if (req.session.login) {
    res.render('users/index');
  } else {
    res.redirect('/users/login');
  }
});

router.get('/login', function(req, res) {
  res.render('users/login');
});

router.post('/login', function(req, res) {
  const loginName = req.body.username;
  const loginPassword = req.body.password;
  db.collection('users').find().toArray(function(err, results) {
    results.map(function(user) {
      if (user['username'] === loginName) {
        const pwCheck = passwordHash.verify(loginPassword, user['password']);
        if(pwCheck === true) {
          req.session.login = true;
          req.session.username = user['username'];
          res.render('users/index');
        } else {
          res.redirect('/users/')
        }
      }
    })
  });
});

Full error

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
    at ServerResponse.header (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/response.js:725:10)
    at ServerResponse.send (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/response.js:170:12)
    at done (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/response.js:962:10)
    at tryHandleCache (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/ejs/lib/ejs.js:208:10)
    at View.exports.renderFile [as engine] (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/ejs/lib/ejs.js:412:10)
    at View.render (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/view.js:128:8)
    at tryRender (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/application.js:640:10)
    at EventEmitter.render (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/Users/camillesebastien/Documents/Programming/Mongo App/node_modules/express/lib/response.js:966:7)

My question

What does this error mean exactly, what is going wrong? And how could I fix this in this situation?

I'm building in Node.JS with Express as router and mongoDB as database. Could it be that it has something to do with that?

I've checked a lot of similar issues on Stackoverflow, but couldn't solve my issue yet ..

Hope someone can help me, thanks in advance!

Just came up a thought:

Could the problem be that I'm testing on localhost, while the mongodb (mongolab) is set on Heroku?

Upvotes: 0

Views: 404

Answers (1)

peteb
peteb

Reputation: 19418

Your problem is that for each result value returned by your DB lookup that matches on password and username you're calling res.render(). You can only call res.render() one time per request. So in theory this will work if only 1 user is returned and their password matches but if the same user exists multiple times and has the same password you're going to make calls to res.render() after it was already sent once.

My suggestion would be to iterate through the list of returned users and then break out after the first time it matches.

Upvotes: 1

Related Questions