NodeJS Tutorial – Part 2, Routing

Note: This is the second part of my NodeJS tutorial. You may want to go back to the first part of this tutorial if you haven’t already read it.

In the first part of this tutorial we looked at reading a document from CouchDB and keeping our markup separate from our code using Haml templates. We arrived at the point where we clicked on a link, but nothing happened. Today we are going to put that right with some very simple routing.

The URL Module

The basis of all routing is the URL. Fortunately, Node has some basic functions which handle reading the URL so we can then decide what the user is actually trying to do.

First, we want to make sure we have included the URL module.

var sys = require('sys'),
fs = require('fs'),
http = require('http'),
url = require('url');

The next step is to extrapolate the path name from the URL that the user has visited:


NodeJS Tutorial with CouchDB and Haml – ErdNodeFlips

The aim of this tutorial is to create a Node powered web app using a CouchDB database and Haml based templates. I wanted something relatively simple that I could do in a couple of sittings, but complex enough to be of some actual use. In the end I opted for a “top 10 list” type application. The functionality being as follows:

  1. To list a number of items
  2. To remove an item from the list
  3. To add an item to the list

Obviously, before getting cracking with this tutorial I had to think up a name for this “killer app” of the Node world.

So I give you ErdNodeFlips! In honour of erdnussflips – the strangely addictive Wotsit type things that taste of peanut butter and stick to the top of your mouth. Yum! (OMG – they even have their own Facebook page!)

All code is available on GitHub.


jQuery Validate URL, adding “http://”

A project we have going on here at ibrow towers involves quite a bit of jQuery Validation. Whilst the Validation plugin is great with the default functions it offers, what makes it truly excellent is the fact that it is easily extendable.

For example, one thing that has been bugging me is to validate a URL the user must type in the initial http://. But why? Can the validation not just assume that if, for example, is typed in, that the user actually meant

Well, after a quick read of the documentation and a hack around this little irritant is now gone. It’s all down to addMethod() which lets you add a custom validation method. Lets create one called complete_url().

jQuery.validator.addMethod("complete_url", function(val, elem) {
    // will contain our validation code
}, 'You must enter a valid URL');

A quick word about return values. If the method returns true, everything is considered OK. However, if false is returned then validation is assumed to have failed.

Our new method needs to do three things:

  1. If no url, don’t do anything
  2. Check that the user had entered http:// in their URL, if not, add it in for them.
  3. Check that the URL is now valid. For this I just used the source for the original url validation method.

Lets translate this into some code:

jQuery.validator.addMethod("complete_url", function(val, elem) {
    // if no url, don't do anything
    if (val.length == 0) { return true; }
    // if user has not entered http:// https:// or ftp:// assume they mean http://
    if(!/^(https?|ftp):///i.test(val)) {
        val = 'http://'+val; // set both the value
        $(elem).val(val); // also update the form element
    // now check if valid url
    // contributed by Scott Gonzalez:
    return /^(https?|ftp)://(((([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(%[da-f]{2})|[!$&'()*+,;=]|:)*@)?(((d|[1-9]d|1dd|2[0-4]d|25[0-5]).(d|[1-9]d|1dd|2[0-4]d|25[0-5]).(d|[1-9]d|1dd|2[0-4]d|25[0-5]).(d|[1-9]d|1dd|2[0-4]d|25[0-5]))|((([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).)+(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).?)(:d*)?)(/((([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(%[da-f]{2})|[!$&'()*+,;=]|:|@)+(/(([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(%[da-f]{2})|[!$&'()*+,;=]|:|@)*)*)?)?(?((([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(%[da-f]{2})|[!$&'()*+,;=]|:|@)|[uE000-uF8FF]|/|?)*)?(#((([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(%[da-f]{2})|[!$&'()*+,;=]|:|@)|/|?)*)?$/i.test(val);

Validating the form with this new method is very straight forward:

    rules: {
        url: "complete_url"

Feel free to use/copy/modify as you see fit. If you do use it, why not let me know, or drop me a trackback?

Have fun

Other jQuery Specific Posts

Sup Crash! Index locked then Terminates. Easy Fix

As many of you know, I use Sup for my emailing needs, and I think it is pretty great. But today, disaster (or at least I initially thought so)!

Instead of opening up and downloading as normal it instead told me it was locked by another process. This in itself is not unusual, sometimes I close the terminal window it is running in by mistake, or shutdown without first closing sup. Hoever, what was different was that the user, host and PID were all blank. When I confirmed it should kill the old process it, well, crashed.

Error: the index is locked by another process! User '' on
host '' is running with pid .
The process was alive as of at least 14 seconds ago.
Should I ask that process to kill itself (y/n)? y
Ok, trying to kill process...

After some searching around nothing was really helping.

In the end I had a poke around in the .sup folder, in which there was a file called lock – I simply removed it and all will work well again!

That was much easier than I thought!

More Sup posts

Awesome WM & NM Applet: Secret Service Operation Failed

I am running Awesome window manager on Lucid Lynx and am using the Network Manager applet to manage my wireless connection. There is a strange error that manes that the wireless can never remember my key.

When I initiate the nm_applet from a terminal it displays the following error:

** Message: secret service operation failed: The name org.freedesktop.secrets was not provided by any .service files

After some searching around on the internets I found a hack that seems to fix the problem.

What you have to do is edit the  /usr/share/dbus-1/services/org.gnome.keyring.service file, comment out where it says Name=org.gnome.keyring
and add the line

For example, my /usr/share/dbus-1/services/org.gnome.keyring.service file looks like this:

[D-BUS Service]
Exec=/usr/bin/gnome-keyring-daemon --start --foreground --components=secrets

Save this, then you’re done.

Easily Add Current File to SVN Within Emacs

As I’ve now been using Emacs for quite a long time, I have picked up a few tips along the way. One thing I’ve been doing more and more is using the shell within Emacs. (For more details see here and here.)

Some of my most used shell commands are using SVN, such as add, revert etc. However, I couldn’t find anywhere to just add/revert the current file I am working on. Fortunately there is Stack Overflow! Someone with a very similar issue to me has had a couple of good answers, which I have “borrowed” and now adding files to my SVN repository is really easy.

First, add the following to your .emacs file

(define-key minibuffer-local-map [f3]
(lambda() (interactive) (insert (buffer-file-name (nth 1 (buffer-list))))))

Now either open up Emacs, or reload your .emacs file:

M-x load-file RET ~/.emacs RET

Now, when you are working on a new file you can easily add it to SVN with the following command:

M-! svn add F3 RET


Hacking about with Node.JS

Update: If you are looking for a NodeJS tutorial, visit this post: NodeJS Tutorial with CouchDB and Haml.

After proclaiming that Node.JS is exciting stuff, today was the first time I’ve actually had the time to play around with it properly. I’ve been thinking about writing a custom FTP server for a project that we’re working on at the moment, and instead of starting from scratch, I thought I’d see if anyone else has tried to do the same. Fortunately I found Andrew Johnston started an FTP server only a few months ago: NodeFTPd on GitHub. I quickly created a clone and tried it out. It didn’t work! Node.JS is such a fast moving target that a lot of the API has been changed in the 3 months since Andrew initially released nodeftpd.

Perfect! This meant that I could play around with Node!

I’ve been hacking about on it for 4 hours or so, you can see my results at GitHub.

So what have my 4 hours of hacking around taught me about Node? Well, it’s not just exciting, it also bloody good fun!

My Perfect Desktop Day 1 – The Base System

arch-linux-logoSo today is the day I start building my perfect system. Before getting going,  I had a good think about which distro to use for the base install. I’ve been using Ubuntu for about 2 years now and love the ease of package management with apt and aptitude. I had a bit of a play around with Ubuntu Karmic yesterday and I must say it looks fantastic, and with Lucid Lynx only a few weeks away it might come as a bit of a surprise to discover that my choice is a distro I’ve never used before: Arch.

Why Arch?

There are three main reasons I’ve picked Arch over Ubuntu, or even Debian.

  1. I really like the idea of Arch’s rolling release system. My laptop is currently running Jaunty and in order to get the latest packages I would have to upgrade to Karmic. With Arch this is less of an issue.
  2. As mentioned in my initial post, the base system should be small, quick and light. With Arch you can pick and choose exactly what you want at installation time, keeping it bloat free.
  3. Finally, Arch will be something new to play with!

After downloading and burning a Net Install ISO I followed the excellent installation guide in the Arch Wiki.

Installation was relatively painless, the only two slight issues being:

I chose Auto prepare for partitioning, but I didn’t really know what filesystem to choose. Eventually I opted for Ext4, with so far, no ill effects.

During Boot Device Selection, again I wasn’t really sure what to do, but after some Googling I found this page, whose advice I followed, but just pressing enter.

I restarted and was greeted with a shell prompt. I quickly pinged Google and my network was still up and running through the ethernet on DHCP.

The next step up a non-root user and X. Again, the Arch documentation is excellent.

Setting up X was relatively simple. I originally decided to not opt for hotplugging, which was a mistake because I only have a USB keyboard and mouse, neither of which I could use in X (muppet of the day award goes to me). After turning off the machine and setting up hotplugging, all was fine!

I have been using the Awesome window manager for about a month now. Awesome is a tiling window manager which is heavily geared towards being keyboard friendly, and as it’s name suggests, it is pretty awesome.

Unlike Jaunty, installing the latest stable version of Awesome was a breeze, I simply ran:

# pacman -S awesome

and edited my ~/.xinitrc file adding:

exec awesome

at the bottom. When I started X again, Awesome was there without any problem.

Sound was equally as simple to install, which was a nice surprise.

So my base system is now setup, with my window manager of choice in place and sound ready and waiting for my music collection. And all this running under 100MB of RAM!

After my first foray into the world of Arch I’m pretty impressed. Pacman is very straight forward to use, after a bit of tweaking here and there it has just worked.

Next time, file management tools.