Create a Real-time Chatting App Using Angularjs & Socket.io

IN This tutorial we’ll Create a Real-time Chatting App Using Angularjs & Socket.io . Tutorial is divided in Three chapter . In First Chapter We’ll learn Basics of socket.io , we’ll also configure Socket.io server for our chatting app . In Second Chapter We’ll be coding backend Of Our Application And In last Chapter we’ll add routes & views To our app . ok Lets get started …

Some Info About socket.io

Created in 2010 by JavaScript developer, Guillermo Rauch, Socket.io aimed to abstract Node.js’ real-time application development. Since then, it has evolved dramatically, released in nine major versions before being broken in its latest version into two different modules: Engine.io and Socket.io. The idea behind Engine.io was to create a more stable real-time module, which first opens a long-polling XHR communication and then tries to upgrade the connection to a WebSockets channel. The new version of Socket.io uses the Engine.io module and provides the developer with various features such as events, rooms, and automatic connection recovery, which you would otherwise implement by yourself.

 

Installing Socket.io

Before you can use the Socket.io module, you will need to install it using npm. To do so, change your package.json file as follows:

{
  "name": "MEAN",
  "version": "0.0.9",
  "dependencies": {
    "express": "~4.8.8",
    "morgan": "~1.3.0",
    "compression": "~1.0.11",
    "body-parser": "~1.8.0",
    "method-override": "~2.2.0",
    "express-session": "~1.7.6",
    "ejs": "~1.0.0",
    "connect-flash": "~0.1.1",
    "mongoose": "~3.8.15",
    "passport": "~0.2.1",
    "passport-local": "~1.0.0",
    "passport-facebook": "~1.0.3",
    "passport-twitter": "~1.0.2",
    "passport-google-oauth": "~0.1.5",
    "socket.io": "~1.1.0"
  }
}

To install the Socket.io module, go to your application’s root folder and issue the following command in your command-line tool:

$ npm install

As usual, this will install the specified version of Socket.io in your node_modules folder. When the installation process is successfully over, your will need be to configure your Express application to work in conjunction with the Socket.io module and start your socket server.

Configuring the Socket.io server

After you’ve installed the Socket.io module, you will need to start the socket server in conjunction with the Express application. For this, you will have to make the following changes in your config/express.js file:

var config = require('./config'),
  http = require('http'),
  socketio = require('socket.io'),
  express = require('express'),
  morgan = require('morgan'),
  compress = require('compression'),
  bodyParser = require('body-parser'),
  methodOverride = require('method-override'),
  session = require('express-session'),
  flash = require('connect-flash'),
  passport = require('passport');

module.exports = function() {
  var app = express();
   var server = http.createServer(app);
   var io = socketio.listen(server);

  if (process.env.NODE_ENV === 'development') {
    app.use(morgan('dev'));
  } else if (process.env.NODE_ENV === 'production') {
    app.use(compress());
  }

  app.use(bodyParser.urlencoded({
    extended: true
  }));
  app.use(bodyParser.json());
  app.use(methodOverride());

  app.use(session({
    saveUninitialized: true,
    resave: true,
    secret: config.sessionSecret
  }));

  app.set('views', './app/views');
  app.set('view engine', 'ejs');

  app.use(flash());
  app.use(passport.initialize());
  app.use(passport.session());

  require('../app/routes/index.server.routes.js')(app);
  require('../app/routes/users.server.routes.js')(app);
  require('../app/routes/articles.server.routes.js')(app);

  app.use(express.static('./public'));

  return server;
};

Let’s go over the changes you made to your Express configuration. After including the new dependencies, you used the http core module to create a server object that wraps your Express app object. You then used the socket.io module and its listen() method to attach the Socket.io server with your server object. Finally, you returned the new server object instead of the Express application object. When the server starts, it will run your Socket.io server along with your Express application.

While you can already start using Socket.io, there is still one major problem with this implementation. Since Socket.io is a standalone module, requests that are sent to it are detached from the Express application. This means that the Express session information is not available in a socket connection. This raises a serious obstacle when dealing with your Passport authentication in the socket layer of your application. To solve this issue, you will need to configure a persistent session storage, which will allow you to share your session information between the Express application and Socket.io handshake requests.

Configuring the Socket.io session

To configure your Socket.io session to work in conjunction with your Express sessions, you have to find a way to share session information between Socket.io and Express. Since the Express session information is currently being stored in memory, Socket.io will not be able to access it properly. So, a better solution would be to store the session information in your MongoDB. Fortunately, there is node module named connect-mongo that allows you to store session information in a MongoDB instance almost seamlessly. To retrieve the Express session information, you will need some way to parse the signed session cookie information. For this purpose, you’ll also install the cookie-parser module, which is used to parse the cookie header and populate the HTTP request object with cookies-related properties.

Installing the connect-mongo and cookie-parser modules

Before you can use the connect-mongo and cookie-parser modules, you will need to install it using npm. To do so, change your package.json file as follows:

{
  "name": "MEAN",
  "version": "0.0.9",
  "dependencies": {
    "express": "~4.8.8",
    "morgan": "~1.3.0",
    "compression": "~1.0.11",
    "body-parser": "~1.8.0",
    "method-override": "~2.2.0",
    "express-session": "~1.7.6",
    "ejs": "~1.0.0",
    "connect-flash": "~0.1.1",
    "mongoose": "~3.8.15",
    "passport": "~0.2.1",
    "passport-local": "~1.0.0",
    "passport-facebook": "~1.0.3",
    "passport-twitter": "~1.0.2",
    "passport-google-oauth": "~0.1.5",
    "socket.io": "~1.1.0",
    "connect-mongo": "~0.4.1",
    "cookie-parser": "~1.3.3"
  }
}

To install the new modules, go to your application’s root folder and issue the following command in your command-line tool:

$ npm install

As usual, this will install the specified versions of the connect-mongo and cookie-parser modules in your node_modules folder. When the installation process is successfully over, your next step will be to configure your Express application to use connect-mongo as session storage.

Configuring the connect-mongo module

To configure your Express application to store session information using the connect-mongo module, you will have to make a few changes. First, you will need to change your config/express.js file as follows:

var config = require('./config'),
  http = require('http'),
  socketio = require('socket.io'),
  express = require('express'),
  morgan = require('morgan'),
  compress = require('compression'),
  bodyParser = require('body-parser'),
  methodOverride = require('method-override'),
  session = require('express-session'),
  MongoStore = require('connect-mongo')(session),
  flash = require('connect-flash'),
  passport = require('passport');

module.exports = function(db) {
  var app = express();
  var server = http.createServer(app);
  var io = socketio.listen(server);

  if (process.env.NODE_ENV === 'development') {
    app.use(morgan('dev'));
  } else if (process.env.NODE_ENV === 'production') {
    app.use(compress());
  }

  app.use(bodyParser.urlencoded({
    extended: true
  }));
  app.use(bodyParser.json());
  app.use(methodOverride());

  var mongoStore = new MongoStore({
    db: db.connection.db
  });

  app.use(session({
    saveUninitialized: true,
    resave: true,
    secret: config.sessionSecret,
    store: mongoStore
  }));

  app.set('views', './app/views');
  app.set('view engine', 'ejs');

  app.use(flash());
  app.use(passport.initialize());
  app.use(passport.session());

  require('../app/routes/index.server.routes.js')(app);
  require('../app/routes/users.server.routes.js')(app);
  require('../app/routes/articles.server.routes.js')(app);

  app.use(express.static('./public'));

  return server;
};

In the preceding code snippet, you configured a few things. First, you loaded the connect-mongo module, and then passed the Express session module to it. Then, you created a new connect-mongo instance and passed it your Mongoose connection object. Finally, you used the Express session store option to let the Express session module know where to store the session information.

As you can see, your Express configuration method requires a db argument. This argument is the Mongoose connection object, which will be passed to the Express configuration method from the server.js file when it requires the express.js file. So, go to your server.js file and change it as follows:

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

var mongoose = require('./config/mongoose'),
  express = require('./config/express'),
  passport = require('./config/passport');

var db = mongoose();
var app = express(db);
var passport = passport();
app.listen(3000);

module.exports = app;

console.log('Server running at http://localhost:3000/');

Once the Mongoose connection is created, the server.js file will call the express.js module method and pass the Mongoose database property to it. In this way, Express will persistently store the session information in your MongoDB database so that it will be available for the Socket.io session. Next, you will need to configure your Socket.io handshake middleware to use the connect-mongo module and retrieve the Express session information.

Configuring the Socket.io session

To configure the Socket.io session, you’ll need to use the Socket.io configuration middleware and retrieve your session user. Begin by creating a new file named socketio.js in your config folder to store all your Socket.io-related configurations. In your new file, add the following lines of code:

var config = require('./config'),
  cookieParser = require('cookie-parser'),
  passport = require('passport');

module.exports = function(server, io, mongoStore) {
  io.use(function(socket, next) {
    cookieParser(config.sessionSecret)(socket.request, {}, function(err) {
      var sessionId = socket.request.signedCookies['connect.sid'];

      mongoStore.get(sessionId, function(err, session) {
        socket.request.session = session;

        passport.initialize()(socket.request, {}, function() {
          passport.session()(socket.request, {}, function() {
            if (socket.request.user) {
              next(null, true);
            } else {
              next(new Error('User is not authenticated'), false);
            }
          })
        });
      });
    });
  });

  io.on('connection', function(socket) {
/* ... */
  });
};

Let’s go over the new Socket.io configuration file. First, you required the necessary dependencies, and then you used the io.use() configuration method to intercept the handshake process. In your configuration function, you used the Express cookie-parser module to parse the handshake request cookie and retrieve the Express sessionId. Then, you used the connect-mongo instance to retrieve the session information from the MongoDB storage. Once you retrieved the session object, you used the passport.initialize() and passport.session() middleware to populate the session’s user object according to the session information. If a user is authenticated, the handshake middleware will call the next() callback and continue with the socket initialization; otherwise, it will use the next() callback in a way that informs Socket.io that a socket connection cannot be opened. This means that only authenticated users can open a socket communication with the server and prevent unauthorized connections to your Socket.io server.

To complete your Socket.io server configuration, you will need to call the Socket.io configuration module from your express.js file. Go to your config/express.js file and paste the following line of code right before you return the server object:

require('./socketio')(server, io, mongoStore);

This will execute your Socket.io configuration method and will take care of setting the Socket.io session. Now that you have everything configured, let’s see how you can use Socket.io and MEAN to easily build a simple chat.

Pin It on Pinterest

Shares

Get the best in web dev

Join dunebook.com and recieve best in web dev , once a week FREE

An email has been Sent to your Inbox ! Please Confirm your Subscription :)