Express3 JS – Accessing and setting session data in routes

Express3 JS – Accessing and setting session data in routes

Problem

I am trying to access nodejs server session variable within a node-mysql query callback but I don’t seem to be able to access or set any of the variables in req.session.

connection.connect();   
    connection.query('SELECT id, firstname, lastname FROM users WHERE username = ? AND password = ?', [username, password] , function(err, rows, fields) {
        if (err) throw err;
        console.log(rows.length);

        if(rows.length > 0){
            console.log('Firstname: ' + rows[0]['firstname'] + ' Last Name: ' + rows[0]['lastname']);
            req.session.firstname = rows[0]['firstname'];
            req.session.lastname = rows[0]['lastname'];
        } else {
            console.log('No Results');
        }
    }); 
    connection.end();

As you can see above I am trying to add the first name and last name to the session as a test to see that the session is working correctly but this will eventually be part of an authentication system.

What is the best way to achieve this. Am I missing some important middleware?

EDIT: Here is the full code in routes.login_process

var mysql = require('mysql');
var md5 = require('MD5');

exports.login_process = function(req, res){
    var username = req.body.username;
    var password = md5(req.body.password);

    var connection = mysql.createConnection({
        host     : 'localhost',
        user     : 'root',
        database : 'node',
        password : 'test',
    });

    connection.connect();   
    connection.query('SELECT id, firstname, lastname FROM users WHERE username = ? AND password = ?', [username, password] , function(err, rows, fields) {
        if (err) throw err;
        console.log(rows.length);

        if(rows.length > 0){
            console.log('Firstname: ' + rows[0]['firstname'] + ' Last Name: ' + rows[0]['lastname']);
            req.session.firstname = result[0]['firstname'];
            req.session.lastname = result[0]['lastname'];
        } else {
            console.log('No Results');
        }
    });
    connection.end();

    res.writeHead(200);
    res.end();
    //res.redirect('http://www.bbc.co.uk');
}

This is being posted from a form which is posted to /login

app.post('/login', routes.login_process);
Problem courtesy of: Daniel West

Solution

The problem is that query is asynchronous, and your res.end() is occurring synchronously after the connection is initiated, thus ending the request before the query callback executes. After the response is ended, the request object can no longer be referenced. Change your code to:

connection.connect();   
connection.query('SELECT id, firstname, lastname FROM users WHERE username = ? AND password = ?', [username, password] , function(err, rows, fields) {
    if (err) throw err;
    console.log(rows.length);

    if(rows.length > 0){
        console.log('Firstname: ' + rows[0]['firstname'] + ' Last Name: ' + rows[0]['lastname']);
        req.session.firstname = result[0]['firstname'];
        req.session.lastname = result[0]['lastname'];
    } else {
        console.log('No Results');
    }

    res.writeHead(200);
    res.end();
});

connection.end();

This causes your response to wait until the query has completed.

Note that I am not sure where exactly the connection.end() will have to go. If it doesn’t work where I put it, try moving it to where res.end() is (however this may or may not work depending on if the library you are using waits for existing queries before ending, or simply kills them)

Solution courtesy of: Nick Mitchinson

Discussion

Leave a Reply

Your email address will not be published. Required fields are marked *