TL;DR version: Down at the bottom is a simple naive RSS proxy written in Coffeescript for Node.js, written as an example.  I explain how to install Node and Coffeescript, and how the proxy works.

There's a lovely blog out there, Elegant Code, which has a series entitled "Baby Steps with Node.JS."   There are a few problems with the site, not the least of which is that the version of node covered is so old the API doesn't jibe with Node 0.4 (the current stable release as of this writing), some of the examples are buggy, and finally they're all written in Javascript.  Now, I've written a lot of articles with Coffeescript in them, but they were huge articles.  I understand if someone got lost.

What is Node.js?  It's a virtual machine for the server that runs Javascript, using Google's V8 engine (the same one running in Google Chrome), but with two extra features: a very tight event loop, and a new language feature, require(), that lets you import libraries.  Node.js both is and is not another programming language in the spirit of Python, Ruby, or PHP: It is in the sense that it can do all of the things those languages to, if and when people get around to writing bindings for things like GUIs and such.

But it's not meant for that.  It doesn't do math as fast as compiled code, it's not elegant the way Python or Ruby can be.  What it's very good at is events, and the web is all about events: requests/responses/waitings-on.  Where another program blocks an HTTP request and idles while it waits for a response from a database, and needs another thread (or process!) to handle another request, Node just puts those transactions into a queue and goes on to the next, round-robin, very very fast.  Plus it's written in Javascript, a language most of us already know, which is a benefit.

Node.js runs on all modern Unix clones, including Apple OS.   Node.js 0.5, the "unstable" build, also runs on Windows.

Once you've installed Node.js, you need the Node Package Manager.  It will let you install common Node packages easily:

curl http://npmjs.org/install.sh | sh

If you know Javascript well, you might have also encountered Coffeescript.  Coffeescript is a little language that compiles to Javascript.  There's a one-to-one correspondence between Coffeescript structures and Javascript structures, which makes Coffeescript easy to learn.  I think Coffeescript is easier to learn and more clear to write, but then I've been writing Python for a very long time.  The Coffeescript compiler is written in Coffeescript and runs in all the major server-side Javascript implementations.  Since we're doing Node, you may as well use that.

Once you've installed NPM, Coffeescript is as simple as:

npm install coffeescript

Okay, enough talk.  We're going to build an RSS proxy-- you'll be getting HTTP output formatted for RSS.  This will work in all browsers but it's best in Firefox because Firefox still makes a heroic effort to parse RSS correctly.

http = require 'http'
url = require 'url'

handle = (server_response) ->
    (response) ->
        if response.statusCode != 200
            console.log(response)
            return
        responseBody = ''
        response.on 'data', (chunk) ->
            responseBody += chunk
        response.on 'end', () ->
            server_response.write(responseBody)
            server_response.end()

myserver = http.createServer (request, response) ->
    feedUrl = 'http://feeds.delicious.com/v2/rss/tag/javascript'
    parsedUrl = url.parse(feedUrl)
    client = http.createClient(80, parsedUrl.hostname)
    client_request = client.request(parsedUrl.pathname, {'host': parsedUrl.hostname})
    client_request.on('response', handle(response))
    response.writeHead(200, {'Content-Type': 'text/html'})
    client_request.end()

myserver.listen(8124)

Coffeescript is a whitespace-delimited language, with some vaguely Rubyesque parsing behaviors.  Many people say if you know Ruby you'll love Coffeescript, but the Python partisan in me loves it too.  Coffeescript's language is so regular that most often you can skip using parentheses.  The example above is inconsistent-- sometimes I use them when they're not necessary, sometimes I don't-- but if you examine the two uses of .on() (in the handler, and in the server declaration), you can see the differences.  The syntax '(argument, argument) ->' is a function declaration and returns an anonymous function. If you understand that, you understand 75% of all Coffeescript, and all you need to know now.

At the top, we use the Node-specific keyword require() to import two libraries we're going to use.  Both of these libraries come with Node, so we're not going to use NPM for anything.  Our target is the "most recent Javascript-tagged stuff on delicious."

Start with the createServer entry.   It takes a function that takes two objects, the request and the response.   The very last line there starts the server, listening at a specified port.  Whenever a browser hits that specified port, the function is called and passed a request object and a response object.

In my example, the function then creates its own HTTP client, makes a call to a specified URL, and sets a handler for the response.

The handler is that first defined function above.  It return a function with the server's response object enclosed within it.  This handler processes the response coming back from the client (in this case, by just storing it), and then, when the client's response is ended, forwards that response through the server's response object and ends the connection.

The magic here is all of the .on() calls.  They handle the events that can happen: when a request gets a response, when the response gets data, when the response ends, and so forth.  What's magical about them is that while they're waiting for those events Node.js can handle any other events for other request/response cycles that are pending.  It's this switchboard power, combined with the familiarity of Javascript, that makes Node.js so nifty.

To run this, just copy the code into a file server.coffee, and run:

coffee server.coffee

Point your browser to http://localhost:8124 and see the magic.