I've got a rather strange problem with my code on production server. On my MacOS it works perfectly, but when I deploy my app, I cannot login. After debug, I've found that I cant load session from req-object. Here's the code of all main parts (settings,, login page and main page after login)
//SETTINGS
var express = require('express');
var app = express.createServer();
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db,
ObjectID = require('mongodb').ObjectID;
var BSON = require('mongodb').BSONPure;
var RedisStore = require('connect-redis')(express);
//connecting to mongo
var server = new Server('localhost', 27017, {
auto_reconnect: true
});
var db = new Db('metadocs-node_db', server);
//setting express app
app.set('view engine', 'ejs');
app.configure(function () {
app.use("/static", express.static(__dirname + '/static'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
secret: "meta-meta",
store: new RedisStore
}));
app.use(express.methodOverride());
});
//login page - POST for /login page
app.post('/login', function (req, res) {
db.collection("users", function (err, collection) {
collection.findOne({
username: req.body.username
}, function (err, doc) {
if (doc && doc.password == req.body.password) {
req.session.user_id = doc._id;
res.redirect('/');
} else {
res.render('login.ejs', {
success_login: 1
});
}
});
});
});
//GET INDEX PAGE - only after login
app.get('/', loadUser, function (req, res) {
db.collection("companies", function (err, collection) {
collection.count(function (err, count) {
res.render('index.ejs', {
total_companies: count,
current_user: req.currentUser['username']
});
});
});
});
//loadUser() is function that creates/loads user session if possible
function loadUser(req, res, next) {
if (req.session.user_id) {
db.collection("users", function (err, collection) {
collection.findOne({
_id: new ObjectID(req.session.user_id)
}, function (err, user) {
if (user) {
req.currentUser = user;
next();
} else {
res.redirect('/login');
}
});
});
} else {
res.redirect('/login');
}
}
Here's the problem code line:
if (req.session.user_id) {
in loadUser() function. The problem is req.session.user_id is empty – I've found it out while debugging every line step-by-step. What I'm doing wrong? It works on my Mac, but does't work on Ubuntu.
I have tried the server you gave the address for at another post for this same problem. Cookies are set without any problems. I logged in successfully. However, one thing caught my attention: expiration time. It is 6/26/12 23:18 GMT now and your cookie expiration is set to 27 Jun 2012 03:18 GMT, which leaves only 4 hours before cookie is expired.
It is perfectly okay to set cookies that will expire in 4 hours; unless your server or a client has wrong date/time or timezone set. Could you please make sure that the working/non-working clients and of course your server have the correct date/times and time zones set up? I believe this is probably the reason of your problem.
On systems I develop, I give cookies expiration times for one year. I validate session on server side without depending on cookie expiration. I do not use connect for cookie and session management since I am always more comfortable doing these things myself. However you can do the same thing while you are still using connect. At session settings, you should set maxAge for cookie to a higher value:
Below code is copied from connect documentation. I have just added maxAge parameter on third line, setting expiration to one day.
connect().
.use(connect.cookieParser('keyboard cat'))
.use(connect.session({ key: 'sid', cookie: { secure: true, maxAge:86400000 }}))
I hope your problem is solved with this.
Here are some things I'd try:
Ubuntu 10.04 and 10.10 have serious bugs (especially 10.10) that cause slow downs if not just instance hangs. http://redis.io/topics/problems
Where are you configuring your redis server connection? I think by default it will look to localhost but in a production environment you typically need to specify the host/port/auth (though I'm not sure if you own the production environment or you are hosting with a 3rd party, so this may not apply.)
Try setting no_ready_check flag to true as well:
client = redis.createClient(port, host, {no_ready_check: true});
client.auth(password, function() {
console.log('Redis client connected');
});
//then pass client into expressjs like so:
...
store: new RedisStore {client: client}
Also add an event handler for 'error' and see if redis is reporting any issues:
client.on('error', function (e) {
console.log(e);
});
Lastly, I'd dump your environment vars in production and your localhost dev to see if there are any configuration differences. Sometimes you set these up in development and forget about them by the time you get to production :)
Hope that helps!
Another solution which I found was: When you are on Debian make sure that you get a different aptitude source so that you can install the most uptodate version of Redis.
This issue kept me busy searching for a few hours...