Xervo

Node.js and Express - Sessions

Node.js and Express - Sessions

Using sessions to keep track of users as they journey through your site is key to any respectable application. Luckily, as usual, using Express with your Node.js application makes it super simple to get sessions up and running.

Express App

Before we do anything else, we need an Express application. Creating an Express app is extremely simple, and the makers of Express do a pretty good job documenting the process.

package.json

{
  "name": "SessionsExample",
  "version": "0.0.1",
  "dependencies": {
    "express": "3.x"
  }
}

app.js

var express = require('express');
var app = express();
app.get('/awesome', function(req, res) {
  res.send("You're Awesome.");
});
app.get('/radical', function(req, res) {
  res.send('What a radical visit!');
});
app.get('/tubular', function(req, res) {
  res.send('Are you a surfer?');
});
//If you host the application on Modulus the PORT environment variable will be defined,
//otherwise I’m simply using 8080.
app.listen(process.env.PORT || 8080);

Now we have three routes defined and available to visit. If you visit one page, it's like you are visiting it for the first time. However, what if we wanted to remember the last page someone visited? We can easily do that with sessions.

Remembering Things

Before we dive in, there is a little bit of setup necessary. We need to “use” the cookie parser and the session features of express before the sessions will be made available. You do this before you define any routes, which in our case would look like so:

app.js

var express = require('express');
var app = express();

app.use(express.cookieParser());
app.use(express.session({secret: '1234567890QWERTY'}));

app.get('/awesome', function(req, res) {
  res.send('Your Awesome.');
});

app.get('/radical', function(req, res) {
  res.send('What a radical visit!');
});

app.get('/tubular', function(req, res) {
  res.send('Are you a surfer?');
});

app.listen(process.env.PORT || 8080);

Since sessions use cookies to keep track users we need both the cookie parser and the session framework. It is important to note that the cookie parser is used before the session, this order is required for sessions to work.

We also provide a secret to the session initializer, which provides a little more security for our session data. Of course you might what to use a key that is a little more secure.

Sessions are accessible through the request object in each route. You can get and set properties just like you would when handling an object normally. For example, lets set some session data in the awesome route.

app.get('/awesome', function(req, res) {
  req.session.lastPage = '/awesome';
  res.send('Your Awesome.');
});

It really is as easy as accessing the session object in the request. Let’s say we want to print the last page the user visited as well.

app.get('/awesome', function(req, res) {
 if(req.session.lastPage) {
   res.write('Last page was: ' + req.session.lastPage + '. ');
 }

 req.session.lastPage = '/awesome';
 res.send('Your Awesome.');
});

Lastly we can apply this to the rest of the routes.

var express = require('express');
var app = express();

app.use(express.cookieParser());
app.use(express.session({secret: '1234567890QWERTY'}));

app.get('/awesome', function(req, res) {
  if(req.session.lastPage) {
    res.write('Last page was: ' + req.session.lastPage + '. ');
  }

  req.session.lastPage = '/awesome';
  res.send('Your Awesome.');
});

app.get('/radical', function(req, res) {
  if(req.session.lastPage) {
    res.write('Last page was: ' + req.session.lastPage + '. ');
  }

  req.session.lastPage = '/radical';
  res.send('What a radical visit!');
});

app.get('/tubular', function(req, res) {
  if(req.session.lastPage) {
    res.write('Last page was: ' + req.session.lastPage + '. ');
  }

  req.session.lastPage = '/tubular';
  res.send('Are you a surfer?');
});

app.listen(process.env.PORT || 8080);

And there it is, a session enabled application.

Using Redis

There is only one major issue with our sessions. Anytime we restart our app, all of the user sessions are lost. I think we can all agree this presents a problem with our updating process.

There are several ways around this problem, but one of the best ways is to use an external store for the session data. More specifically, we can use a Redis store. This way the session data is completely separate from our running application.

To set up Redis with Express sessions, we need an extra module. This module is the Redis client used by connect and helps create a streamlined solution for connecting Redis to Express. First we have to make sure its in our package.json.

package.json

{
  "name": "SessionsExample",
  "version": "0.0.1",
  "dependencies": {
    "express": "3.x",
    "connect-redis": "1.4.x"
  }
}

Then we have to require it.

var express = require('express');
var app = express();
var RedisStore = require('connect-redis')(express);

app.use(express.cookieParser());
app.use(express.session({secret: '1234567890QWERTY'}));

//...

Notice that we pass Express to the Redis connector. This is required for Express and the Redis store to play nice with each other, which makes the process a whole lot easier later.

In order to set up the Redis store with our sessions, we are going to modify our app.use call. The session initializer not only takes a secret, but a store as well. As you can probably guess, this is used to tell the session manager where to put all the session data. All we have to do is pass in an object it can use instead of its native storage.

var express = require('express');
var app = express();
var RedisStore = require('connect-redis')(express);

app.use(express.cookieParser());
app.use(express.session({
  store: new RedisStore({
    host: 'localhost',
    port: 6379,
    db: 2,
    pass: 'RedisPASS'
  }),
  secret: '1234567890QWERTY'
}));

//...

It’s as simple as that. The RedisStore constructor can take all the normal options you would expect. In this case we are going to use database 2 with the password we use to authenticate with our Redis instance.

Now all of our session data will stored safely in our Redis database. This also means that any time we restart our node application, the session data is immune from being reset because it is not stored under the same process as our application.

What about Mongo?

So some of you out there might be wondering if you can use MongoDB to store your session data. Well, using Mongo in place of Redis in our previous example is actually just as simple as using Redis. Instead of connect-redis you just use, you guessed it, connect-mongo.

package.json

{
  "name" : "SessionsExample",
  "version" : "0.0.1",
  "dependencies" : {
    "express" : "3.x",
    "connect-mongo" : "0.3.x"
  }
}

Just add a few “Mongo”s where you see “Redis” and it all falls into place.

var express = require('express');
var app = express();
var MongoStore = require('connect-mongo')(express);

app.use(express.cookieParser());
app.use(express.session({
  store: new MongoStore({
    url: 'mongodb://root:myPassword@mongo.onmodulus.net:27017/3xam9l3'
  }),
  secret: '1234567890QWERTY'
}));

//...

It is honestly that simple. Of course there are a lot more options you have when creating your MongoStore instance, but the example above gets you the basic functionality and will start storing your session data in your Mongo database.

So there are the basics behind Express sessions. As you can see, it is not complicated, and just requires a little setup to get rolling. Don’t forget, if you have any questions or comments, throw them out below. We are never afraid of feedback.

What is Xervo?

Xervo makes deploying applications in the public cloud or your own data center easy. Node.js, PHP, Java, Python, Nginx, and MongoDB supported. Full Docker support included in Enterprise version. It’s free to get started.

Share This Article

comments powered by Disqus