Part 3 - Building a Backend with Node, Mongo and Socket.IO
Part 3 – Building a Chatroom Backend with Node.js, Socket.IO and Mongo
Welcome to Part 3 of Node.js Tutorial Series: A chatroom for all! In this part, I will show you how to use your existing express-based node.js app to create a chatroom backend with WebSocket support.
What are WebSockets? What is Socket.IO?
WebSocket is a protocol designed to allow web applications to create a full-duplex channel over TCP (i.e. to have bi-directional communication) between the web browser and a web server. It is fully compatible with HTTP and uses TCP port number 80. WebSockets allowed web applications to become real-time and support advanced interactions between the client and the server. It is supposed by several browsers including Internet Explorer, Google Chrome, Firefox, Safari and Opera.
Adding Socket.IO to Package.json
Package.json is a file that holds various metadata relevant to the project including its dependencies. NPM can use this file to download modules required by the project. Take a look at this interactive explanation of package.json and what it can contain.
Let’s add Socket.IO to the project as a dependency, now there’s two ways to do that.
1. If you have been following the tutorial series and have your project in Visual Studio all setup, all you have to do is right-click on the npm part of the project and select “Install New npm Packages…”
Once the window has opened, you will want to search for “socket.io”, select the top result and make sure the “Add to package.json” checkbox is checked. Next press the “Install Package” button. This will install socket.io into your project and add it to the package.json file.
2. If you’re on OS X or Linux, you can achieve the same action as the above by running the following command in the root of your project folder.
npm install --save socket.io
Adding Socket.IO to app.js
The next step is to add socket.io to app.js. You can easily achieve this by replacing the following code.
To be replaced with:
This will capture the HTTP server in a variable called serve and pass that server so that the socket.io module can attach to it. The last code block takes the serve variable and executes the listen function which starts the HTTP server.
Logging a User Joining and Leaving
Ideally, we want to log a user joining the chatroom. The following code easily helps us accomplish that by hooking a callback function to be executed on every single “connection” event via WebSocket to our HTTP server. In the callback function, we call console.log to log that a user connected. We can add this code after we call serve.listen (or before, it doesn’t matter).
To do the same for when a user leaves, we have to hook up to the “disconnect” event for each socket, we do that by adding the following code inside after the console log of the previous code block.
Finally, the code will look like this:
Broadcasting a Message Received on the Chat Channel
Socket.IO gives us a function called emit that we can use to send an event. What we want to do is any message received on the “chat” channel and broadcast it to all the other connections on this socket.
To do this, we want to listen to the “chat” channel and call emit with the broadcast flag in the callback for the “connection” event.
UPDATE: THE LINE SHOULD BE: socket.broadcast.emit('chat', msg); TO BROADCAST TO THE RIGHT CHANNEL. IT HAS BEEN CORRECTED BELOW.
Finally, the code will look like this:
Saving Messages to a NoSQL Database
The chatroom should save chat messages to a simple datastore. Normally, there are two ways to save to a database in Node; you can use a database-specific driver or you can use an ORM. In this tutorial, I will show you how to save the messages to MongoDB. Of course, you can use any other database you like, including SQL databases like PostgreSQL or MySQL.
You should make sure you have a MongoDB to connect too. You can use a third-party service to host your MongoDB such as MongoHQ or MongoLab. Take a look at this tutorial to see how you can create a MongoDB using the MongoLab Add-On in Azure. (You can stop reading when you get to the section “Create the App”, just make sure to save the MONGOLAB_URI somewhere you can access easily later.)
Once you have created a MongoDB and you have the MONGOLAB_URI for the database – Under Connection info that you have copied to your clipboard – you will want to ensure that URI is available to the application. It is not best practice to add sensitive information such as this URI into your code or into a configuration file in your source code management tool. You can add the value to the Connection Strings list in the Configuration menu of your Azure Web application (such as in the tutorial you used) or you can add it to the App Setting list (with Name “CUSTOMCONNSTR_MONGOLAB_URI”). On your local machine, you can add it to the environment variables with the name “CUSTOMCONNSTR_MONGOLAB_URI” and value of the URI.
The next step is to add support for mongodb to our project. You can do that by adding the following line to the dependencies object in package.json. Make sure to save your changes to the file.
Right-click on the npm part of the project in the Solution Explorer to reveal the right-click context menu. Select “Install missing packages” from the content menu to install the mongodb package so that it can be used as a module.
We want to import that module to be able to use the mongodb client object in app.js. You can add the following lines of code after the first require(‘’) function calls, such as on line 11.
We want to connect to the database using the URI we have in the CUSTOMCONNSTR_MONGOLAB_URI environment variable and once connected, we want to insert the chat message received in the socket connection.
As you can see in the above code, we use the process.env object to get the environment variable value. We go into a collection in the database and we call the insert function with the content in an object.
Every message is now being saved into our MongoHQ database.
Emitting the Last 10 Messages Received
Off course, we don’t want our users to feel lost once joining the chatroom, so we should make sure to send the last 10 messages received to the server so at the very least we can give them some context. To do that, we need to connect mongo. In this case, I am refraining from wrapping all of the socket code with one connection to the database so that I can still have the server working even if it loses the database connection.
I will also want to sort and limit my query to the last 10 messages, I will use the Mongo-generated _id as it contains a timestamp (although in more scalable situations, you will want to create a dedicated timestamp in the chat message) and I will call the limit function to limit the results to only 10 messages.
I will stream the results from Mongo so that I can emit them as soon as possible to the chatroom as they arrive.
UPDATE: The channel to emit on should be 'chat'.
The above code does the job as explained in the previous paragraphs.
Deploying to Azure
You can redeploy to Azure by following the past tutorials (such as part 2).
Now we have a chat system capable of broadcasting a message received via websockets to all other connected clients, it saves the message to the database and retrieves the last 10 messages to give context to every new user who joins the chatroom. You can follow @ramisayar on Twitter to keep up to date.