Introduction to the node.js module express.js

My last post covered module loading in node…or at least try to cover the basics in an understandable way… This time, it is time to create something a bit more useful, a proper web application, using a module called “express”. And instead of me talking a whole lot about what I am about to talk about, let’s just get into it…

The first step is to install express. This is done using the NPM as always. The only thing to really decide is whether or not you want to install it globally using the -g parameter, or just locally. Me, I am just going to do it locally, so I use the following command

npm install express

If you install it globally, you can use express to create a “skeleton” application by running the following command

express -s -J <folder name>

This will give you a fullblown express app to start working with. But as I intend to explain the basics, I will start from scratch, and thus just install express to begin with.

As you install express, you get a whole heap of other modules as well, as you can see from the console output. These are modules needed by express, and something you can just ignore…

Ok, now that we have express installed, it is time to get started with some coding. And as always, at least when I do it, I start with a new server.js file.

The first thing we need to do, is to “require” express, and create an instance of it.

Once we got an instance of the express webserver, it is time to define what it should to. And that is obviously to serve up content to users making requests over HTTP. The way that this is done, is by telling express what verb you want to handle, GET, PUT, POST etc, and at what path. In this case, I want to respond to GET requests at the path “/”.

And how do you respond? Well, you give express a callback to execute when someone makes an HTTP request to the corresponding path. And in this callback, we get access to a “request” object and a “response” object. Much like we do in ASP.NET and so on…

And finally, we tell express to listen to a specified port. In my case, I will put it at 8080.

Final code? Like this

var express = require('express');

var app = express();

app.get('/', function(req, resp) {
resp.end('Hello from express.js');
});

app.listen(8080);
console.log('Listening on port 8080');

Running this code, and then browsing to http://localhost:8080/ results in something like this

image

Ok, so we have a fully working webserver, with routing and stuff, in 7 lines of code. And that is because I am very verbose…

Unfortunately, if we look at the response we are getting using for example Fiddler, we will see that it is a bit “crippled”. It looks like this

HTTP/1.1 200 OK
X-Powered-By: Express
Date: Wed, 14 Aug 2013 13:28:10 GMT
Connection: keep-alive
Transfer-Encoding: chunked

15
Hello from express.js
0

Ok, so what is wrong with that? Well, it lacks a few somewhat important headers. It lacks a “Content-Type” and “Content-Length” header. These are pretty important headers, at least if you intend to serve something more interesting than the string “Hello from express.js”. So we better add those…

var express = require('express');

var app = express();

app.get('/', function(req, resp) {
var body = 'Hello from express.js';
resp.setHeader('Content-Type', 'text/plain');
resp.setHeader('Content-Length', body.length);
resp.end(body);
});

app.listen(8080);
console.log('Listening on port 8080');

Ok, that’s better! Now the response looks good! None of that “15” and “0” stuff that for some reason was added in the previous response.

However, this is pretty standard stuff…doesn’t express sort that stuff out for us? Well, of course it does! If we use resp.send() instead of resp.end(), express will sort it all out. So let’s try that…

In this case, I will just add another path to try that. in this case, I will use “/send”…

...

app.get('/send', function(req, resp) {
resp.send('Hello from express.js');
});

...

The response is now a little different though… Express just assumes that we are doing text/html, and using UTF-8, which will be true in most cases. If you need to change it, you can, but for now, let’s just leave it…

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 21
Date: Wed, 14 Aug 2013 13:35:42 GMT
Connection: keep-alive

Hello from express.js

Sweet! that’s all I ever need! Now I can start building awesome things… ;)

Well, there is obviously more… The first thing is to try and get the callbacks out of my server.js file. I don’t want to have my entire application in one file, so moving the callbacks out to a module seems like a good idea to start with.

To do this, I create a new module, which is documented in my last blog post. In this case, i put a index.js file in a “routes” folder, and require it at the start of my script.

Inside that index.js file, I export the callbacks that I want, which to begin with is just one, which I call “index”. It looks like this

exports.index = function(req, resp) {
resp.send('Welcome to express.js');
};

Once I have my new module created and required, I use the exported “index” method to handle requests to “/index” like this

var express = require('express'),
routes = require('./routes/');

...

app.get('/index', routes.index);

...

Using this technique, I can get all my callbacks removed, and keep the server.js file clean. But to be honest, if I were to get a lot of paths, I would probably create another module responsible for hooking up the paths to the handlers… But for this simple demo, I will leave it like this…

Ok…what’s next? What about more complex paths? Well, that is not a whole lot more complicated… Let’s start by creating a handler that can handle path information. It looks like this

exports.path = function(req, resp) {
var out = 'myParam = ' + req.params.myParam;
var qps = Object.keys(req.query);
for (var i = 0; i < qps.length; i++)
{
out += '; ' + qps[i] + ' = ' + req.query[qps[i]];
}
resp.send(out);
};

Ok, so what does this code do? Well, first off, it looks at the “params” property on the request object. This property contains a parameters defined when defining the path to use for the handler. In this case, I have defined a parameter called “myParam”, which I will get back to.

Next, it looks at the request.query property, which contains the values passed as querystring parameters. Once it has concatenated this parameters, it returns it to the client…

The path that is defined for this handler looks like this

...

app.get('/path/:myParam', routes.path);

...

And calling the server using http://localhost:8080/path/mypath?myparameter=myvalue returns the following view

image

So we now know how to respond to requests using very simple content, but what if we want something more complex. Is there no view engine for us to use? Of course there is! So let’s have a look at that…

There are several view engines available using for example jshtml, nhaml or basic html. I have chosen to use jshtml as it feels comfortable to use for me as an ASP.NET dev.

Once you have chosen a view engine, you need to install it and tell express to use it. Installing it is just NPM:ing it, which in my case means executing “npm install jshtml-express”, which installs a jshtml module prepared for use with express. And telling express to use it involves a few lines of code like this

...

var app = express();

app.engine('jshtml', require('jshtml-express'));
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');

...

So what does these 3 lines of code do? Well, the first one tells express that views with the fileextension jshtml should be served up using the jshtml-express module. The second one tells express where it should look for views. in this case that means a subfolder called “views”. And the last one tells express that if no fileextension is used, it should default to jshtml.

Ok, now we have a view engine configured. Let’s create a simple view…

Inside my subfolder “views” I create a new file called index.jshtml, and add the following

<html>
<head>
<title>jshtml</title>
</head>
<body>

<h1>Welcome @locals.title</h1>
<ul>
@for(var i = 0; i < @locals.tasks.length; i++) {
var task = locals.tasks[i];
<li>
<a href="#@task.id">@task.name</a> @(task.complete ? " - Done!" : "")
</li>
}
</ul>

</body>
</html>

This is pretty self-explanatory, except for the “local” variable, which is a variable send from the handler to the view. It is the model in MVC…

Once the view is created, I create a new handler… The handler defines the model to use, by passing it to the response objects “locals” method. It then calls the response.render() method, telling it what view to render. Like this

exports.jshtml = function(req, resp) {
resp.locals({
title:'Chris',
tasks: [
{id: 1, name: 'Call mum', complete: false },
{id: 2, name: 'Call wife', complete: true },
]
});
resp.render('index');
}

And finally, I hook it up to a path in express…

...

app.get('/jshtml', routes.jshtml);

...

And the result? Well, ugly but working

image

The last thing I want to show you in the post is how to handle form posts. This is not very complicated, but it involves a few steps, so I thought it would be a good ending to the post…

The first step is to create a form to post. I do this using a jshtml file that looks like this

<html>
<head>
<title>Form</title>
</head>
<body>

<h1>My Form</h1>

@if (locals.postedName != undefined) {
<div>Thanks for the post @locals.postedName</div>
}

<form action="@locals.path" method="POST">
<div>
<label for="Name">Name: </label>
<input type="text" name="Name" />
</div>
<input type="submit" value="Submit" />
</form>

</body>
</html>

As you can see, it first verifies if there is a “postedName” in the locals. if there is, it thanks for the post. If not, it just ignores it. Next it creates a simple form, posted to a url defined in the locals.

Now we need to serve it up, which requires a new handler, which is hooked up to the path “/form”. It looks like this

exports.formGet = function(req, resp) {
resp.locals({ path: req.url, postedName: req.query['name'] });
resp.render('form');
}

For now, you can ignore the postedName that is pulled from the query. This will make sense in a few minutes…

The next thing is to create a handler for the posted data. This handler is simple, and looks like this

exports.formPost = function(req, resp) {
console.log('Form posted with name: ' + req.body.Name);
resp.redirect('/form?name=' + req.body.Name);
}

All it does is logging the post to the console, including the posted name, and then redirects back to the GET handler, including the name in the querystring.

Registering this handler with express is pretty much a repeat of every other registration I have done in this post, except for the fact that I use the post() method instead of the get() one

...

app.get('/form', routes.formGet);
app.post('/form', routes.formPost);

...

Sweet, ready to go! Let’s try it out!

Unfortunately, starting the server, browsing to “/form” and posting the form, I am met with the following screen

image 

Hmm… Name is undefined… Hmm…

Well, there is a little gotcha here. Express does not know how to parse the body by default. We have to tell it by adding a parser to the request pipe like this

...

var app = express();

app.use(express.bodyParser());

...

Once we have that body parser in place, we can go ahead and try it again. And the result is now a little different

image

It is still ugly, but it is ugly in the way it is supposed to be… :)

Ok, that was it I think… There will be a follow up post that talks about handling errors in express, as well as adding basic authentication and other features into the request pipe. But for the sake of keeping my post semi-short, I will stop at this this time!

Here is the code: hello-express.zip (2.15 kb)

OBS! The zip-file does not contain the required modules… Remember to run “npm install” to get the required modules installed.

Cheers!

Add comment