home nodejitsu.com


Vote on HN

About the author

Name
Marak Squires
marak
marak
Location
New York, NY

About this article

Date Released:
Friday, Nov 26 2010
Code Examples:
  • loginExample.js

Also by this author

  • spawning hookio hooks
  • using nodejitsu for nko
  • top node module creators
  • the west coast hack haus
  • ten node apps that need to exist

About nodejitsu

nodejitsu is a node.js application hosting company from new york city.

we are community leaders in the node.js project.

we build awesome open-source projects that you love and use.

Follow @nodejitsu

sessions and cookies in node

Session management is a major piece of any serious web application. When building a site, it is likely you will want the ability to persist a user's identity over multiple requests without having to have them re-login again and again. A common method for persisting a user's login over multiple http requests, is called setting a "cookie". Now almost all web developers have some idea of what a cookie is, but in this article we will dive into the specifics of actually implementing a cookie / session persistence system from scratch in node.js through exploring the session.js library and the response library.


Getting Started

First, we are going to need some logic for implementing session management. Crack JavaScript developer inimino was nice enough to release the following module, so we will build on that. In this module, only one method is exported: "lookupOrCreate". If we dive into this method a little bit, we can see it takes two options, a request object and an options hash.

This "lookupOrCreate" method will inspect the headers of the incoming request object and determine if there is any value set for the cookie field ( note: the actual header name is "Set-Cookie", but node refers to this header as "cookie"). If lookupOrCreate finds a cookie, it will retrieve the session object from memory, else it will create a new session for that request.

Now, the tricky part here is that if we've created a new session, we need to set the cookie in the response header so the client knows it has a session. Unless we explicitly set a cookie in the response header, "lookupOrCreate" will never find your session cookie.

To set the cookie in the http response you can do something like:

 var session = sessions.lookupOrCreate(request,{
   lifetime:604800
 });

 response.writeHead(200, {
   'Content-Type': 'text/plain', 
   'Set-Cookie', session.getSetCookieHeaderValue()
 });

Even better then using response.write though, is using response.setHeader. This will not close the response, and allow for further manipulation down the request/response processing chain...kinda like a proper middle-ware!

 response.setHeader('Set-Cookie', session.getSetCookieHeaderValue());

Note: You will need the response module for this to work, it should be pulled into core eventually.


Creating a super simple session middle-ware

In node.js, an accepted standard for building middleware is the following:

 function( request, response, callback) {

   // perform some logic on the request or response objects
   console.log(request.url);


   // then fire our callback, and pass the request 
   // and response objects down the chain
   callback(request, response, function(){

   });

 }

Following this standard, a "middle-ware" for node.js's httpServer is nothing but a function that accepts three arguments: a request object, a response object, and a callback. Building on this very simple convention, we can implement de-coupled layers of middleware, each with its own responsibility. In our case, our middleware will be responsible for establishing sessions!


get session.js!


Using session.js as a middle-ware

var http = require('http'), 
    session = require('./lib/core').session;

// let's create a basic http server!
http.createServer(function (request, response) {

  // before we process any part of the request, let's use the session middle-ware!
  session(request, response, function(request, response){

    // now we can access request.session

    // after the session middleware has executed, let's finish processing the request
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('request.session: \n' + JSON.stringify(request.session, 2, true));
    response.end();

  });

}).listen(8080);

/* server started */  
console.log('> hello world running on port 8080');


Magic Monkey Punched Middle-ware Sessions (automatically patches httpServer)


Creating a super simple login / logout feature

One of the best things about having a persistent session object per user, is having the ability to create user logins. The actual way you want to implement your login is somewhat arbitrary. Here is a basic pattern to follow. Please, remember this method is just an example:

    var http = require('http'),
        session = require('./lib/core').magicSession();

    // let's create a basic http server!
    http.createServer(function (request, response) {

      // please note: this is just an example of how to hook auth into session.js, its not ideal at all

      // super basic logout
      if(request.url === '/logout'){
        request.session.data.user = "Guest";
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('You\'ve been logged out');
        response.end();
        return;
      }

      // let's hardcode a username and password variable into the url
      var urlParams = require('url').parse(request.url, true).query || {};

      if(typeof urlParams.name != 'undefined'){
        // if the "name" parameter has been sent, lets log in as that user
        request.session.data.user = urlParams.name;
      }
  
      // request.session.data.user always defaults to "Guest"
      if(request.session.data.user == "Guest"){
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Hello, you are the Guest user');
        response.end();
      }
      else{
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Hello, you are ' + request.session.data.user);
        response.end();
      }


    }).listen(8080);

    /* server started */  
    console.log('> hello world running on port 8080');

Once you have this running you can do the following:

GET http://localhost:8080/
// returns: Hello, you are the Guest user

GET http://localhost:8080/?name=Marak
// returns: Hello, you are Marak

GET http://localhost:8080/
// returns: Hello, you are Marak

GET http://localhost:8080/logout
// returns: You've been logged out

GET http://localhost:8080 
// returns: Hello, you are the Guest user

Huzaah! There you go! session.js is open-source, so lets get hacking!