Chris Tankersley

Moving JavaScript Server-Side with node.js

Posted on 2011-04-04

When Twitter decided to basically tell developers 'Stop Making Twitter Clients,' that somewhat struck a cord with me. It wasn't because I make Twitter clients but the attitude. I decided to start working on FlyAway to help people switch from Twitter to Identi.ca, which runs on StatusNet, an open source microblogging platform.

The announcement struck an even deeper cord with client developers like Ed Finkler, who runs the Spaz project. Since Spaz is an identi.ca client, I decided to switch back to it and started lurking around in the #spaz channel on freenode. Ed had an idea to create a Social Network proxy service to make it easier for clients to talk to all these different social networks. He called it Honeybadger.

To help out, I decided to create a server for the project. Since Honeybadger is being written in JavaScript I elected to build it in node.js, a server-side JavaScript interpreter that is built using Google's V8 engine.

Server-Side Javascript?

JavaScript is generally considered a Client-Side language since it runs in the client's browser. You do all your coding and then pray that the browser does what you want since each browser has its own JavaScript engine, just like how they have their own rendering engines for HTML and CSS. Your code might talk to external servers, but it doesn't run on the server.

Recently an interest has been to use JavaScript on the server. According to Wikipedia, which has been proven to be infallible, there are many different options for running JavaScript on the server. I chose node.js mainly because its one of the most popular right now.

Setting up node.js

Installing node.js is pretty straight forward. Download and compile:

$ ./configure
$ make
$ make install

I cheated and used homebrew since I like using that as a package manager for OS X:

$ brew install node

Using JavaScript Outside the Browser

Server-Side JavaScript is pretty much like Client-Side, except you don't have a DOM to deal with. The code is the same. What does 'Hello World!' look like? Put this one-liner in 'hello-world.js':

console.log('Hello World!');

To run this in node.js, just call node and pass it the name of the script to run:

$ node hello-world.js
Hello World!

Yes, I agree. That is totally awesome! OK, it doesn't really show anything, but the idea is you can now use JavaScript to start working on things. node.js has a huge list of modules that can be used and its own package manager, npm.

CalcJS and WWWCalcJS- Two Functional Examples

Lets make two scripts - CalcJS, which is a command line calculator, and WWWCalcJS, which is the online version. We'll pass them some numbers, add them together, and return the result.

CalcJS

We'll invoke the calculator with 'node calc.js 2 2' and just have it spit out the results on the console.

var one = parseInt(process.argv[2]);
var two = parseInt(process.argv[3]);
console.log('The Answer is: '+(one + two));

process is a global object that holds information about the process that is running. In our case, we pull the arguments that are passed in (which start counting at 0, with 0 being node, 1 being the script name) and store them. Since they get passed in as strings, I cast them to Integers so that we don't get string concatenation. Lets change this to take an arbitrary number of... numbers:

var numbers = [];
for(var i = 2; i < process.argv.length; i++) {
        numbers.push(parseInt(process.argv[i]));
}
var total = 0;
for(var j in numbers) {
        total += numbers[j];
}
console.log('The Answer is: '+total);

Yes, this can be done with one loop but that's not the point. Since this is JavaScript, we can use arrays and loops just like on the client side. With the new addition, we can do this:

$ node calc.js 1 2 3 4
The Answer is 10

WWWCalcJS

node.js can also be run as an HTTP server by invoking the correct modules. For the next example, we'll start a server on port 9000 and pass it two GET parameters: one and two. The URL and command line invocation will look this:

URL: http://localhost:9000/add?one=2&two;=2
CLI: node wwwcalc.js localhost 9000







var http        = require('http');
var url         = require('url');
var querystring = require('querystring');

http.createServer(function (req, res) {
        switch(url.parse(req.url).pathname) {
                case '/add':
                        dispatch_add(req, res);
                        break;
        }
}).listen(process.argv[3], process.argv[2]);
console.log('Server running at http://'+process.argv[2]+':'+process.argv[3]+'/');

function dispatch_add(req, res) {
        var req_query = querystring.parse(url.parse(req.url).query);
        var one = parseInt(req_query.one);
        var two = parseInt(req_query.two);
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.write('The Answer Is '+(one + two));
        res.end();
}

Lines 1-3 pull in some modules that come with node.js. We'll use these to start the server and do some manipulation of the URL to find out what we need to do. Line 5 creates the server object, and we pass in an anonymous function that will handle the logic for the server itself. We go dead simple and just respond to a URL that starts with '/add' (everything else is just ignored).

If the URL starts with '/add', we call the 'dispatch_add' function (line 14). It takes the request and response objects that get passed into the server so that we can get the query string and output a response. Line 15 separates out the query parameters into a JavaScript object.

Since this HTTP server is bare-bones, we need to output the headers to the client. We throw out an HTTP Code 200 and let it know we're going to send it plain text (line 18). On the next line we write out to the client, and then close out the response. Line 20 is needed so that the client knows we're finished sending a response.

Wrapping all the way back up to line 11, we actually start the server. We spit out a line to the console letting us know that the server is started as well as the address and port we should use.

JavaScript is Now a Viable Server-Side Technology

Servers like node.js allow users to create scripts and even services in a language that they already know. JavaScript is an easy way to write event-driven software and is a widely-accepted language. Will it supplant languages like PHP or Ruby for web technologies? No, but like everything else you should use the right tool for the job. Using available modules, you can create a node.js-based web server to render static websites, dynamic websites, APIs, interact with external libraries, and all sorts of things.

Browse through the modules that are available in npm, and just google. There are many different articles on ways to use node.js. You can also hit up the IRC channel on freenode under #node.js for support and questions. Take your knowledge of JavaScript, or begin expanding it, but moving it out of the browser and onto the server.


Comments