How To Write A Simple Node.js/MongoDB Web Service for an iOS App

Learn how to create a simple Node.js and MongoDB web service for an iOS app in this tutorial. By Michael Katz.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 6 of this article. Click here to view the first page.

Serving up Content With Express

It’s easy to serve up static files using Express.

Add the following statement to the require section at the top of index.js:

path = require('path');

Now add the following line just after the app.set statement:

app.use(express.static(path.join(__dirname, 'public')));

This tells Express to use the middleware express.static which serves up static files in response to incoming requests.

path.join(__dirname, 'public') maps the local subfolder public to the base route /; it uses the Node.js path module to create a platform-independent subfolder string.

index.js should now look like the following:

//1
var http = require('http'),
    express = require('express'),
    path = require('path');
 
//2 
var app = express();
app.set('port', process.env.PORT || 3000); 
app.use(express.static(path.join(__dirname, 'public')));
 
app.get('/', function (req, res) {
  res.send('<html><body><h1>Hello World</h1></body></html>');
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Using the static handler, anything in /public can now be accessed by name.

To demonstrate this, kill your Node instance by pressing Control+C, then execute the commands below in Terminal:

mkdir public; edit public/hello.html

Add the following code to hello.html:

<html></body>Hello World</body></html>

This creates a new directory public and creates a basic static HTML file.

Restart your Node instance again with the command node index.js. Point your browser to http://localhost:3000/hello.html and you’ll see the newly created page as follows:

web_hello

Advanced Routing

Static pages are all well and good, but the real power of Express is found in dynamic routing. Express uses a regular expression matcher on the route string and allows you to define parameters for the routing.

For example, the route string can contain the following items:

  • static terms/files only matches http://localhost:300/pages
  • parameters prefixed with “:”/files/:filename matches /files/foo and /files/bar, but not /files
  • optional parameters suffixed with “?”/files/:filename? matches both “/files/foo” and “/files
  • regular expressions/^\/people\/(\w+)/ matches /people/jill and /people/john

To try it out, add the following route after the app.get statement in index.js:

app.get('/:a?/:b?/:c?', function (req,res) {
	res.send(req.params.a + ' ' + req.params.b + ' ' + req.params.c);
});

This creates a new route which takes up to three path levels and displays those path components in the response body. Anything that starts with a : is mapped to a request parameter of the supplied name.

Restart your Node instance and point your browser to: http://localhost:3000/hi/every/body. You’ll see the following page:

web_hieverybody

“hi” is the value of req.params.a, “every” is assigned to req.params.b and finally “body” is assigned to req.params.c.

This route matching is useful when building REST APIs where you can specify dynamic paths to specific items in backend datastores.

In addition to app.get, Express supports app.post, app.put, app.delete among others.

Error Handling And Templated Web Views

Server errors can be handled in one of two ways. You can pass an exception up the call stack — and likely kill the app by doing so — or you can catch the error and return a valid error code instead.

The HTTP 1.1 protocol defines several error codes in the 4xx and 5xx range. The 400 range errors are for user errors, such as requesting an item that doesn’t exist: a familiar one is the common 404 Not Found error. 500 range errors are meant for server errors such as timeout or programming errors such as a null dereference.

You’ll add a catch-all route to display a 404 page when the requested content can’t be found. Since the route handlers are added in the order they are set with app.use or app.verb, a catch-all can be added at the end of the route chain.

Add the following code between the final app.get and the call to http.createServer in index.js:

app.use(function (req,res) { //1
    res.render('404', {url:req.url}); //2
});

This code causes the 404 page to be loaded if it is there is no previous call to res.send().

There are a few points to note in this segment:

  1. app.use(callback) matches all requests. When placed at the end of the list of app.use and app.verb statements, this callback becomes a catch-all.
  2. The call to res.render(view, params) fills the response body with output rendered from a templating engine. A templating engine takes a template file called a “view” from disk and replaces variables with a set of key-value parameters to produce a new document.

Wait — a “templating engine”? Where does that come from?

Express can use a variety of templating engines to serve up views. To make this example work, you’ll add the popular Jade templating engine to your application.

Jade is a simple language that eschews brackets and uses whitespace instead to determine the ordering and containment of HTML tags. It also allows for variables, conditionals, iteration and branching to dynamically create the HTML document.
Update the list of dependencies in package.json as follows:

{
  "dependencies": {
    "express": "3.3.4",
    "jade": "1.1.5"
  }

Head back to Terminal, kill your Node instance, and execute the following command:

npm update

This downloads and installs the jade package for you.

Add the following code directly beneath the first app.set line in index.js:

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

The first line above specifies where the view templates live, while the second line sets Jade as the view rendering engine.

Execute the following command in Terminal:

mkdir views; edit views/404.jade

Add the following code to 404.jade:

doctype html
body
    h1= 'Could not load page: ' + url

The first two lines of the Jade template create a new HTML document with a body element. The third line creates an h1 element inside the body element due to the indent. Spacing is important in Jade! :]

The text of the h1 element is the concatenated value of “Could not load page” and the value of the url parameter passed in as part of the res.render() in index.js.

As a quick check, your index.js file should now look like the following:

var http = require('http'),
    express = require('express'),
    path = require('path');
 
var app = express();
app.set('port', process.env.PORT || 3000); 
app.set('views', path.join(__dirname, 'views')); //A
app.set('view engine', 'jade'); //B

app.use(express.static(path.join(__dirname, 'public')));
 
app.get('/', function (req, res) {
  res.send('<html><body><h1>Hello World</h1></body></html>');
});

app.use(function (req,res) {
    res.render('404', {url:req.url});
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Restart your instance of Node and use your browser to load the URL http://localhost:3000/show/a/404/page. You’ll see the page below:

web_404

You now have enough starter code in index.js to accept incoming requests and provide some basic responses. All that you’re missing is the database persistence to turn this into a useful web application that can be leveraged from a mobile app.