Creating a Simple Publishing-Subscribe Messaging App Using Node.js, Express, and Faye

Tuesday, May 1, 2012

Introduction

I have been playing around with Node.js for a bit. You know--the hot new kid on the programming block that everyone is talking about. I'm getting old and maybe this is just a mid-life crisis, but I like learning the cool, new stuff. JavaScript on the server! Who knew?

Why Node

Node is popular for a couple reasons. For one thing, it is JavaScript, so pretty much every web developer already knows it. The engine that executes the scripts server side is called V8. This is the very same engine that executes JavaScript scripts in your Chrome browser and it is fast. The thing that makes Node.js standout from other languages is that it is by it's JavaScript nature, non-IO blocking. There is some good information about it on Orielly, but essentially, what this means is Node.js handles it's I/O asynchronously and this makes it quite preforment.   Node.js does not tie up threads waiting on long running call-outs, instead it uses what is called an event loop to handle all of the call-outs at the same time. That's not to say that Node.js doesn't have it's issues, it does. It's still a bit immature (especially on a Windows machine) and you have to be careful with the whole asynchonous thing as it can cause some unusual results. Still, I like it. I am having fun learning it.

​Setting It Up:

First off, a quick shoutout to the guys at http://nodecasts.org/ for getting me started. The screencast was very helful. Because the age of the screencast, the code was a little bit depricated (Express was the culprit), but it didn't take much to find the new code syntax and correct the problems. I am going a little bit further in my example and making the message call via AJAX instead of in the command line via CURL.

To get Node.js up on your machine, go to http://nodejs.org and follow their installation instructions.

Once node is up and running, got http://npmjs.org/ and install the Node.js Package Manager. If your a .Net guy it is the Nuget equivalent, or the Ruby's Gem equivalent.

On my Windows machine, I've setup a directory call Node (i.e. c:\Node\ ). I then created a project folder ( C:\node\faye_sample ).

From the command line, navigate to to your project folder and run the following commands.

  • npm install express
  • npm install faye

These commands will install the Express and Faye packages on your machine that you can then reference in your code.

Express is basically a Node framework that gives you MVC styled architecture inspired by Sinatra in the Ruby world. For this example, I am only going to create a one file application and use Express for some shortcuts. There are some really good Express screencasts at NodeTuts, so if you want to go further with Node, I recomment that you give those a look at.

Faye is subscriber/publisher framework that allows any HTTP client to talk to a server real time as well many clients talk to each other real time via the server.

​The Server Code

Okay, lets take a look at the server side code. First thing I need to do is get a reference to Express and Faye.

var express = require('express'),
    faye = require('faye');

 

The next thing I need to do is initialize Faye on the server.

var bayeux = new faye.NodeAdapter({
    mount: '/faye',
    timeout: 45
});

In case you are wondering about that funny variable name. Faye uses the Bayeux protocol as its mechanism to transport the messages back and forth.

Next step, initialize the Node server using the Express wrappers.

var app = express.createServer();
app.configure(function() {
    app.use(express.bodyParser());
    app.use(express.static(__dirname + '/public'));
});

The express.bodyParser will parse the request coming in and place the data coming in into the req.body object. As you will later see, it will contain my incoming message that I can then get to rather easily.

The variable __dirname is the current directory my application is running in. the function express.static is basically telling Node that all my static content is located in the static folder inside the current application folder.

To capture the posts from the different browsers, I need to set up a route handler that will capture a post request and then broadcast that request to all of the client listeners.

app.post('/message'function(req, res) {
    bayeux.getClient().publish('/channel', { text: req.body.message });
    console.log('broadcast message:' + req.body.message);
    res.send(200);
});

The first line of code is capturing the post request from "/message" and passing in the request and response object on a callback function. The callback function then gets the message from the request and publishes it to the clients. I am also logging the message so I know that the server got the message. Because I called bodyParser when I configured my server, I now have access to the req.body.message which contains my message from the client.

The last thing I need to do is start up my node server. In this case, I am listening on port 8123.

bayeux.attach(app);
app.listen(8123);

The Client

Okay, for simplicity sake here, I am going to create two HTML files with exact same code in it and then hard code Client #1 and Client #2 in the respective files. So lets look at the client code.

In my HTML markup, I have the following elements.

                <h1>Chat Client #1</h1>
		<div id="messages"></div>
		<textarea rows="2" cols="35" id="chat"></textarea>
		<input type='button' value='Chat' id='fire' />

I need to grab a script reference to the latest jQuery, and also the Faye script on the client side.

<script src='/faye/browser/faye-browser.js'></script>

 

With the Faye reference, I can then setup a listener that will update my HTML when ever some sends out a message.

                        var client = new Faye.Client('/faye',{
				timeout: 20
			});
			
			client.subscribe('/channel'function(message) {
				$('#messages').append('<p>' + message.text + '</p>');
			});

 

Next: I am going to use jQuery to post a message when ever a user clicks on a chat button.

    		    var $chat = $('#chat');
    		    $('#fire').on('click',nullfunction() {
    		        var url = 'http://localhost:8123/message';
				
    		        var message = {message: 'Client 1: ' + $chat.val()};
    		        var dataType = 'json';
    		        $.ajax({
    		            type: 'POST',
    		            url: url,
    		            data: message,
    		            dataType: dataType,
    		        });
    		        $chat.val('');
    		    });
    		    

That's it!

I can now start up my server from the command line.

  • ​node server.js

Next, I open two browsers and start chatting.

2 browsers chatting via node server

Now, if I look at my command line server log I should see the messages because I put a line in the code to log them.

server log of faye messages

​Conclusion

I set up a GitHub repository with this code in it that you can take a look at. As I explore Node some more, I'll probably post some more posts on Node.js so stay tuned.

References

comments powered by Disqus