0

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);
Daniel West
  • 1,808
  • 2
  • 24
  • 34
  • 1
    What exactly is not working? Is it giving you an error, or are the values simply not there on the next request? If it is the latter, post the code that you are using to read the values from the session. – Nick Mitchinson Mar 29 '13 at 19:36
  • 1
    `req.session` only exists after you've `app.use`'d the `express.session` middleware (which depends on `express.cookieParser ` itself). – robertklep Mar 29 '13 at 19:37
  • @NickMitchinson Seems to be an issue where the callback for connection.query doesn't have access to req. All im doing to check the values in session is console.log(req.session) – Daniel West Mar 29 '13 at 19:38
  • @NickMitchinson I have added the full chunk of code... – Daniel West Mar 29 '13 at 19:41
  • @NickMitchinson TypeError: Cannot read property 'session' of undefined – Daniel West Mar 29 '13 at 19:47

1 Answers1

1

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)

Nick Mitchinson
  • 5,452
  • 1
  • 25
  • 31
  • You may want to handle the error within the callback instead of throwing it as well. If you do not, the error will be thrown out of the callback, and the response will not be sent. If you do want to throw the error instead of handling it, make sure you end the response before you do or the client will be left hanging waiting for the response. – Nick Mitchinson Mar 29 '13 at 20:01
  • Cheers, I should have picked up on that! Yeah i'm currently using the node-mysql module for the database. Plan to use mongodb though. Just getting to grips with node and express first. – Daniel West Mar 29 '13 at 20:14