0
votes

I'm new to nodejs and its routes system. I'm getting "Can't set headers after they are sent." only on production mode only on Heroku (It works fine locally).

// Login =========================================

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

router.post('/login', function(req, res, next){
    var username = req.body.username;
    var password = req.body.password;

    req.checkBody('username', 'Username field is required').notEmpty();
    req.checkBody('username', 'Password field is required').notEmpty();

    req.checkBody('password', 'Invalid Credintials').len(8, 20);
    req.checkBody('username', 'Invalid Credintials').len(4, 20);

    var errors = req.validationErrors();

    if(errors) {
    res.render('login.ejs', {errors: errors});
    } else {
        passport.authenticate('local-login', {
            successRedirect : '/list', // redirect to the secure list section
            failureRedirect : '/', // redirect back to the signup page if there is an error
            failureFlash : true // allow flash messages
        })(req, res, next);
    }
});

// Functions ================================================

function ifLoggedIn(req, res, next) {

// if user is authenticated in the session, carry on 
    if (req.isAuthenticated()) {
        return next();
    }
  console.log("cannot found in session");
  res.redirect('/');

}

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


app.use('/', router);
}

// Error Log of Heroku

2015-08-20T07:37:07.490091+00:00 app[web.1]: Error: Can't set headers after they are sent. 2015-08-20T07:37:07.490096+00:00 app[web.1]: at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11) 2015-08-20T07:37:07.490098+00:00 app[web.1]: at ServerResponse.header (/app/node_modules/express/lib/response.js:718:10) 2015-08-20T07:37:07.490099+00:00 app[web.1]: at ServerResponse.send (/app/node_modules/express/lib/response.js:163:12) 2015-08-20T07:37:07.490101+00:00 app[web.1]: at done (/app/node_modules/express/lib/response.js:957:10) 2015-08-20T07:37:07.490103+00:00 app[web.1]: at View.exports.renderFile [as engine] (/app/node_modules/ejs/lib/ejs.js:355:10) 2015-08-20T07:37:07.490105+00:00 app[web.1]: at View.render (/app/node_modules/express/lib/view.js:126:8) 2015-08-20T07:37:07.490106+00:00 app[web.1]: at tryRender (/app/node_modules/express/lib/application.js:639:10) 2015-08-20T07:37:07.490108+00:00 app[web.1]: at EventEmitter.render (/app/node_modules/express/lib/application.js:591:3) 2015-08-20T07:37:07.490109+00:00 app[web.1]: at ServerResponse.render (/app/node_modules/express/lib/response.js:961:7) 2015-08-20T07:37:07.490111+00:00 app[web.1]: at /app/routes/routes.js:7:7 2015-08-20T07:37:07.490112+00:00 app[web.1]: at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) 2015-08-20T07:37:07.490114+00:00 app[web.1]: at next (/app/node_modules/express/lib/router/route.js:131:13) 2015-08-20T07:37:07.490115+00:00 app[web.1]: at ifLoggedOut (/app/routes/routes.js:181:10) 2015-08-20T07:37:07.490117+00:00 app[web.1]: at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) 2015-08-20T07:37:07.490118+00:00 app[web.1]: at next (/app/node_modules/express/lib/router/route.js:131:13) 2015-08-20T07:37:07.490119+00:00 app[web.1]: at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)

1
Could you please explain where do you get error exactly i mean at what part to what you try to do?Viddesh
Hello, please describe your issue in detail. SO is not a dumping ground for your buggy code. (Also, the error tells you exactly what's wrong - your application tries to send header after it has been already sent -> rendering should be only called once in a request-response cycle)lazlojuly
@viddesh, here i added the error log and improved my question. sorry for not doing so from the beginning. i have found the error in the ifLoggedIn() and ifLoggedOut() but i'm not able to fully comprehend the reason behind the error.Bahi Hussein
@lazlojuly, yea i think this is the issue. would redirect() and next() affect each other? can you please check the IfLoggedIn function and help me understand the cause of the issueBahi Hussein
I see that you have figured out the issue by yourself so I have improved on your answer instead of answering this myself.lazlojuly

1 Answers

2
votes

This issue was in the ifLoggedIn and ifLoggedOut functions where next() callback was called followed by the redirect() making two subsequent rendering calls. By using return with the next() callbacks these mistakes can be avoided.

original code:

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

fixed version:

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

Alternatively if else could have been used properly (without the need of return):

if(req.isAuthenticated()){
    res.redirect('/list');
} else {
    next();
}

Still, using return is a good practice to avoid mistakes like these.