Keeping Node.js app.js clean + custom middleware for express

neat stuff

This post has two purposes: to continue the previous one showing ways to improve the organization of routes and secondly to see how to add your own middleware to an express application.

The previous version have a problem when it comes to the routes. We require all of them with a single require command but we were applying them one by one.

var routes = require('./routes');
...
// We set routes
app.use('/', routes.home);
app.use('/guestbook', routes.guestbook);
Use a contructor in routes/index.js

There Is More Than One Way To Do It claims the Programming Perl book on the cover. Something that, undoubtedly, fits Node.js. There is more than one style in Node-foo, and I guess that you have to choose the way that better fits your needs. My need here was to minimize the code to initialize the routes in the main file of the Node.js express application. We change the routes/index.js to have a constructor with a parameter: the express app itself

This is routes/index.js

/**
 * routes/index.js
 * All routes are here to import all of them just with one command
 * in the main app.js
 * https://github.com/pello-io/simple-express-mongoose
 * Pello Altadill - http://pello.info
 */
var home = require('./home');
var guestbook = require('./guestbook');

module.exports = function (app) {
	home(app);
	guestbook(app);
}

See those calls to home and guestbook? we are passing again the express app instance to each route file, where we also change its shape to get that parameter. Be careful! now we have to specify the complete route to '/guestbook/', something that in fact makes everything much more clear

/**
 * routes/guestbook.js
 * The router for guestbook operations.
 * Keep in mind that here '/' refers to '/guestbook/'
 * https://github.com/pello-io/simple-express-mongoose
 * Pello Altadill - http://pello.info
 */
var mongoose = require('mongoose');
var GuestBook = mongoose.model('GuestBook');

module.exports = function (app) {

    /**
    * get
    * GETs all guestbook data.
    */
    app.get('/guestbook/', function(req, res) {
    ...
}

home.js does the same

/**
 * routes/home.js
 * The home page, just renders the jade template
 * https://github.com/pello-io/simple-express-mongoose
 * Pello Altadill - http://pello.info
 */
module.exports = function (app) {

	app.get('/', function(req, res) {
	    res.render('index.jade' , {title: 'Home page'});
	});

}

And now, this is how the main app.js looks like. Instead of using each route separately, now it's enough to do it once. In this example may seem a useless effort, but when your app evolves to have many different routes dispersed in many files we will add all of them with just one command, keeping our main app.js nice and clean.

/**
* app.js
* Main entrypoint for the app
* https://github.com/pello-io/simple-express-mongoose
* Pello Altadill - http://pello.info
*/
var express = require('express');
var bodyParser = require('body-parser');

var models = require('./models');
var routes = require('./routes');
var middleware = require('./middleware');

var app = express();

// If we want to use post data:
app.use(bodyParser());

// We set middlewares
middleware(app);

// We set all the routes with one single call
routes(app);

// We set static content
app.use(express.static('public'));

// And there we go, listening on port 3000
app.listen(3000, function () {
    console.log('now listening on http://localhost:3000');
});
Creating custom middleware

If you are using connect or express then it's probably making use of more than one middleware. In a nutshell, the middleware is some code that is executed between the request and te response in a Node.js web application. Therefore, whenever you call app.use(whatever) you are already applying middleware like routes, bodyParser, etc...

Some dummy middlewares

Let's create some middleware for testing. The first will just log the requests made to our server and the second will log a message. The second its useful only to observe the way the middlewares are chained for each request. As we can have more than one custom middleware and following the same style of the routes and models, we'll create a folder called middleware with an index.js file that will load and apply all the middlewares.

This is how the logrequest middleware looks like. Don't forget the next() call, or the request will not go on to next middleware!!!

/**
* logrequest
* this just logs every request to console
*/

module.exports = function logRequest (req, res, next) {
  console.log('request received: ');
  console.log("["+req.method+"] " + req.url);
  console.log(req.body);
  // and go on... if you don't call next the request will hang
  next();
}

And this is the dummy middleware

/**
* dummyddleware.js
* A dummy middleware just to see the order it is being called
*/

module.exports = function dummyddleware (req,res, next) {
	console.log('Dummy middleware');
	next();
}

And the index.js that applies them both to the expres app

/**
 * middleware/index.js
 * All middleware are here to import all of them just with one command
 * in the main app.js
 * Note that maybe this is not always desirable if you want to apply
 * any other middleware in a different order into app.js file.
 * @greetz for any
 */
var logrequest = require('./logrequest');
var dummyddleware = require('./dummyddleware');

module.exports = function (app) {
	app.use(logrequest);
	app.use(dummyddleware);
}

Finally as we have seen before, in the main entry-point we can just add

var middleware = require('./middleware');
...
// We set middleware
middleware(app);

At the time of writing this I'm receiving very valuable feedback about how to organize your projects, even with fullstack app generators. Which one is the best? It's the usual devious question that comes from a sales manager or the like. It depends on the project nature, don't you think?

You can clone, download(at this point of development), copy-paste this project from git. Don't forget to get the required node modules to make it work!

by Pello Altadill 5 Days ago - 94 hits

Node.js + express routes + mongoose, simple and separated

There are plenty of examples out there explaining how to develop a webserver in node.js using the express framework. There are also great books like Professional Node.js and Smashing Node.js introducing details about express among many other topics. But there is also, imho, a big problem: all of them show different ways to solve the same problem. In addition to that there were changes in the framework (Express has recently changed to version 4) and some documentation and samples could be deprecated, so if y...

by Pello Altadill 07/23/2014 23:45:40 - 198 hits

More »

Setting different config files in Node.js

External config files When it comes to configuration options it is always desirable to avoid hardcoding config values in our code. Even more, if we are using different config values in development and production environments it is necessary an easy way to switch from one to another. This also becomes useful when your code is public but you want to hide some config files. In Node.j...

by Pello Altadill 07/22/2014 00:52:26 - 179 hits

More »

Enabling basic authentication for MongoDB databases

MongoDB is extremely easy to install and run. If you are not able to make it work maybe you could feel more confortable using Access or even excel. Well, sorry for that. This short article is but a quick and dirty guide to enable basic authentication in mongodb, and how to create one database with its own user (not a superadmin) with just read/write permissions. If you run mongo...

by Pello Altadill 07/20/2014 00:37:15 - 207 hits

More »

Python language basics

Python in 21 minutes (or so) For a developer is not enough to know one programming language, it is often said that is good to know many of them. After all the language is but a mere tool to build programs. Python has been around for many years and one of my pending task was to take a look at it. Some friends (@Eugenia4v,@Claw_Shadow,@D00m3dr4v3n) are always tellin...

by Pello Altadill 07/12/2014 23:51:05 - 317 hits

More »

A night out with Jasmine

A night out with Jasmine Unit testing is much more than a tool for ensuring that a program behaves as expected. Nowadays it's the key for new development techniques such as TDD and BDD in which you begin writing tests before the required code. It's all about requirements and behaviour; developers must focus on understanding the requirements instead of thinking about the way they implement the code. In the event that you've forgotten the fundamental benefits of unit testing here you have a quick...

by Pello Altadill 04/23/2014 00:37:18 - 1681 hits

More »

Arkapong

This a classic pong-like game that takes some ideas from Arkanoid. Basically two paddles try to hit the ball until one of them fails but, from time to time the rules can change if special bricks are touched. Red: invert ball direction White: triple ball Yellow: smaller paddles Blue: bigger paddles Green: speed up ball Orange: change...

by Pello Altadill 04/07/2014 07:35:33 - 1661 hits

More »

Getting started with Node

Few days ago, a very dear friend of mine came up to my place with a present. It was a nodejs book. This is a new or maybe it would be more accurate to say an emergent technology which brings back an old idea that I used to hear of long time ago: a server side javascript. That was something that was supposed to exist somewhere, as it was mentioned in the prefaces of many javascript related papers: ...

by Pello Altadill 03/17/2014 23:48:44 - 1925 hits

More »

Calcular el IBAN con php

Los organismos internaciones se han vuelto a poner de acuerdo para poner unificar los números de cuenta y gracias a ello todos los programadores y DBAs del mundo ya estamos enfrascados en la tarea de adaptar programas, validaciones, campos de las BBDD y un largo etcétera. En cada país el código de cuenta corriente puede variar y a través del IBAN se intenta unificar la forma de esa cuenta de tal forma que sea validable. ...

by Pello Altadill 01/18/2014 00:01:21 - 1986 hits

More »