Lets try the new Express 4.0 version

Express is a well-known library for building simple web applications. Also express is a really modular library you can easily add other modules and middlewares to make your life easier. With the new version, the structure is more modular and the core of the code is split into multiple modules.

Getting started, as you remember the old express version had express generator built-in which is now separated to `express-generator` module. To generate application boilerplate:

npm install -g express-generator
mkdir express4
cd express4
express
npm i

Now the express should be installed with the dependencies of other libraries. The server start is hidden in `bin/www` file, run it and open browser localhost:3000. The browser page should look like this:

2014-04-10-215445_542x263_scrot 

The changes that 4.0 bring are more like structural, all the previously included middlewares are now separated modules:

The use of the middleware is same with app.use, so the setup looks like this:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// Routes setup
app.use('/', routes);
app.use('/users', users);

The greatest change is the Router support, which allows to create sub-routes with separated middleware stack. Read more about the router usage in Express guide router. For example, in the project you have created users routes, which contains separate router instance with authentication middleware which is applied only for this router.

var express = require('express');
var router = express.Router();

router.use(function authenticationMiddleware (req, res, next) {

    if (new Date().getSeconds() % 2) {
        return next();
    }

    next(new Error('User not allowed to page'));
});

/* GET users listing. */
router.get('/', function(req, res) {
  res.send('respond with a resource');
});

module.exports = router;

If you are using the old version of express 3.5 and want to upgrade to express 4, make sure you have look through all the middleware changes. There are a lot of middlewares which might not be compatible with the new session middleware. But in overall there is not any big changes that breaks the compatibility and upgrading to newer version should be easy.

Advertisements

Book Advanced Express Web Application Development

Book cover

I had opportunity to  read a book “Advanced Express Web Application Development”. There are many books written about using Express.js framework, some of are good and some not so good. This book gives you good ground understanding of the Node.js Express usage and example of how to develop solid application. Through the book you are working on single-page application called “Vision“, which covers both the client side (Backbone) and server-side development.

Some of the key points and topics what I liked in this book:

  • Single application through book, not just random code snippets which does not give the understanding how the project structure should be
  • Test driven development – TDD all the server-side code is tested
  • Scaling: vertical and horizontal – many books miss this chapter but that’s the reason you are using Node.js, right ? Actually this is large topic and needs to be covered more, maybe in future “someone” writes a book about scaling in Node.js.
  • Lastly there is the chapter of making your application ready for production

Well if you are using Express daily  this is “must read” book because there are many useful tips an guides you might find and apply in your projects.

IRC bot with Node.js

The old IRC protocol remains still pretty active as it is main communication for people who does not like to use Facebook. I have used IRC chat for long time and there are plenty of helpful people for discussing about programming.

Main thing is that you can connect to irc server by opening TCP connection and simply sending the commands. Lets give example with telnet, to connect you only need to:

  • telnet irc.freenode.net 6667
  • NICK username
  • USER username 8 * : Full Name
  • JOIN #node.js

As a result these command should bring you to node.js channel and you should see all the text stream. To send message to channel PRIVMSG #node.js :Test message, before sending message you have to specify who(user) or what channel receives the message. Another important thing is to follow the PING messages sent by server. If the user does not replay to the PING with PONG, user gets timeout and is disconnected from server.


All this can be really simply implemented in Node.js, the evented programming comes helpful when dealing with network. Here comes small example of IRC bot, which sends the user uptime if command @uptime is written to channel.

var net = require('net')
  , util = require('util')
  , exec = require('child_process').exec;

var options = {
    PORT: 6667
  , HOST: 'irc.freenode.net'
  , NICK: 'Miska'
  , CHANNELS: [ '#node.js', '#javascript', '#randomChan' ]
  , USER: {
        ALLOWED: [ 'risto_' ]
  }
};

var command = [
    { match: /^PING/, emit: 'pong' }
  , { match: '@uptime', emit: 'uptime' }
];

var socket = net.connect(options.PORT, options.HOST, function() {
    console.log('Connection up to irc server');
});

socket.setEncoding('ascii');
socket.setNoDelay();

socket.on('connect', function() {

    setTimeout(function() {
        socket.write(util.format('NICK %s\n', options.NICK));
        socket.write(util.format('USER %s 8 *: %s\n', options.NICK, 'Full Name'));
        socket.write(util.format('JOIN %s\n', options.CHANNELS.join(','))); 
    }, 10000);
});

socket.on('timeout', function() {
    console.log('TIMEOUT for connection');
    console.log('Total of bytes written: ' + socket.bytesWritten);
});

/**
 * Custom command for bot send the uptime
 */
socket.on('uptime', function() {
    var child = exec('uptime', function(err, stdout, stderr) {
        if (err) throw err;
        else {
            options.CHANNELS.forEach(function(elem) {
                var response = util.format('PRIVMSG %s :%s\n', elem, stdout);
                console.log(response);
                socket.write(response);
            });
        }
    });
});

socket.on('pong', function() {
    console.log('PONG message back');
    socket.write('PONG\n');
});

socket.on('data', function(data) {
    var cleanedData = data.toString().trim();
    console.log(cleanedData);

    command.forEach(function(command) {
        if (cleanedData.match(command.match)) {
            socket.emit(command.emit);
        }
    });
});



Expressive way to handle errors in expressjs

When you have created new express project, the errors get handled a bit differently in dev mode and in production mode. In development mode the errors are show in express error template with some error stack if showStack is set to true. But in production mode you will be shown as less as you need the ‘Internal Server Error’ on plain text page. Here is our plan to make the production side errors more fancier and keep the development side informative.

First take of the production mode default error handling.

app.configure('production', function(){
  //app.use(express.errorHandler()); 
});

Add app.error which will be run on if error is caught. I have already created views for errors which needs some customization on jade template.

app.error(function(err, req, res, next){
  if (err instanceof NotFound) {
    res.render('error/404.jade', { title: 'Not found 404' });
  } else {
    res.render('error/500.jade', { title: 'Error', error: err });
  }
});

And in the end of app.js, added the /* router which routes all the unknown pages to 404 page by throwing NotFound errror. So by going to url like this localhost:3000/path/that/does/not/exist does not lead you to the some GET that route does not exist, but into 404 page.

// The 404
app.get('/*', function(req, res){
    throw new NotFound;
});

function NotFound(msg){
    this.name = 'NotFound';
    Error.call(this, msg);
    Error.captureStackTrace(this, arguments.callee);
}

Running now the server in production mode NODE_ENV=production node app.js, should give on visiting unknown page this:

And on the 500 error which are thrown when user tries to go in /add/post page without permission:

This is one way to handle the errors in expressjs, if you know any better methods feel free to post. The code is also added into github.

Creating simple blog with Node.js: flash messages

One way to give user feedback is to use the flash messages, after certain action you display information. Example user deletes the post and is redirected to main page, now display the information if all were successful or not.

To make use of the flash messages you need to add the cookieParser

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session({ secret: 'wasdsafeAD' }));
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

This is the way to add information to flash messages, you can acces the object by req.flash().

if (!err) {
  req.flash('info', 'Post has been sucessfully edited');
}

To use it in all the view so I would not have to pass the flash object into every render function, is to register helper.

app.dynamicHelpers({
...
  flash: function(req, res) {
    return req.flash();
  }
});

Also i have added into layout.jade before header partial !=partial(‘alert’, flash) and in view partial is the message look.

mixin showAlert(alerts)
    for alert in alerts
      div #{alert}

- if (flash.info)
  div.alert.alert-info
    mixin showAlert(flash.info)

- if (flash.success)
  div.alert.alert-success
    mixin showAlert(flash.success)

- if (flash.error)
  div.alert.alert-error
    mixin showAlert(flash.error)

Creating npm package from scratch

The Node Package Manager seems to do wonderful job, it is simple to understand and has really well built up. I have created one simple IMDB scraper, which I want to add into repository so I’ll share my tips step by step.

1. I have already created directory imdb-rscraper, put all the package files in the folder, if you have many files create separate folder lib.

2. Create new file called package.json(touch package.json),this is the file where all the metadata is listed. You could basicaly use this template.

{
    "name": "imdb-rscraper",
    "author": "No Public Name here",
    "homepage": "https://veebdev.wordpress.com/",
    "version": "0.0.1",
    "description": "Scraping the data from IMDB with JQuery selectors",
    "main": "imdb-rscraper.js",
    "keywords": [
        "imdb",
        "scraper"
    ],
    "dependencies" : {
        "jsdom": ">= 0.2.12"
    },
    "repository" : {
        "type" : "git",
        "url" : ""
    }
}

3. Now make symlink the package folder run npm link. Creates link /usr/local/lib/node_modules/imdb-rscraper -> /home/risto/node/imdb-rscraper

4. Create the README file for better understanding even for yourself, give brief overview how to use your library, tool.

5. Before publishing you have to create user in repository npm adduser fill the user fields and the publish npm publish. After the last step you should see something like this. Give feedback if I missed something.

npm http PUT https://registry.npmjs.org/imdb-rscraper
npm http 201 https://registry.npmjs.org/imdb-rscraper
npm http GET https://registry.npmjs.org/imdb-rscraper
npm http 200 https://registry.npmjs.org/imdb-rscraper
npm http PUT https://registry.npmjs.org/imdb-rscraper/0.0.1/-tag/latest
npm http 201 https://registry.npmjs.org/imdb-rscraper/0.0.1/-tag/latest
npm http GET https://registry.npmjs.org/imdb-rscraper
npm http 200 https://registry.npmjs.org/imdb-rscraper
npm http PUT https://registry.npmjs.org/imdb-rscraper/-/imdb-rscraper-0.0.1.tgz/-rev/2-18de2cfa3e62cb38e8b13c84deb5db16
npm http 201 https://registry.npmjs.org/imdb-rscraper/-/imdb-rscraper-0.0.1.tgz/-rev/2-18de2cfa3e62cb38e8b13c84deb5db16
+ imdb-rscraper@0.0.1

6. Visit npmjs.org and search for your package with the declared information for each version.