Create a REST API with Node.js, Express, and MongoDB

Creating a REST API with Node.js is simple, fast, and efficient. Node.js is lightweight, non-blocking, and perfect for data intensive applications. Node.js, although young, has a strong community backing. The Node.js community provides a vast array of modules that can be leveraged to simplify the implementation process. Node.js also has support for many widely used offerings. In this post, we will use MongoDB with Node.js. We will also use two modules, Express and Monk.

Let’s briefly explain each of these components:

  • Node.js – a lightweight platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications.
  • MongoDb – is an open-source document database, and the leading NoSQL database.
  • Express.js – a web application framework for Node
  • Monk – a tiny layer that provides simple yet substantial usability improvements for MongoDB usage within Node.js

I. Prerequisites:

  • A basic understanding of RESTful design principles.
  • Install Node.js – see nodejs.org and click Install.
  • Install MongoDb – see MongoDb.org
  • Install Express.js globally – npm express -g
  • (Install Node.js packages for Express, Monk and Mongo DB – Don’t worry about this now, I’ll explain below)

Let’s now create a REST API that enables us to maintain a database of cars.

II. Create a Node.js / Express project

In the prerequisites section, we installed Express.js. To do so, we ran

npm express -g

This installs express globally and provides us with a new express binary installed in NODE_HOME/bin directory.

We now use express to create our project:

express cars_project

This creates a new directory, cars_project, that contains our project files. app.js is our project’s entry point

Since we plan to use Monk and MongoDB, we must add them as dependencies.

To add the dependent modules, edit the package.json file located in the cars_project directory and add monk and mongodb to the dependencies list:

{
  "name": "cars-project",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.5.1",
    "mongodb":"*",
    "monk":"*"
  }
}

Finally, we must install all dependent modules into our local project.
To do so, navigate to the cars_project directory and run:

npm install

III. Test our server

cars-project/app.js is our project entry point. app.js provides the logic to start our web server. Yes, you heard the correctly, app.js implements the http server, which means we do not need a third party web server.

Also, Node.js creates our web server in just a few lines of code. Wow!

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

Let’s start our application and test it!

node app.js

Point your browser to http://localhost:3000, you should see the Express welcome page.

If you are curious as to how that is rendered, browse the app.js code

IV. Define the REST API

(For a detailed explanation of REST. See my post on RESTful Design principles)

GET /cars Get a list of all cars
GET /cars/<id> Get the car identified by <id>
POST /cars Create a new car
PUT /cars/<id> Update the car identified by <id>
DELETE /cars/<id> Delete the car identified by <id>

IV. Implement/Stub the REST API using Node.js/Express.js

To start, lets create a new JavaScript file to handle the requests to our car resource. This file will be responsible for handling the requests described in the table above. For example, this file will handle GET /cars, GET /cars/<id>, POST /cars, etc.

Create a folder cars_project/resources to contain our new file carres.js.
For now carres.js should export the following stubbed out public functions:

exports.findAll = function(req, res) {
    // logic to handle GET /cars
};

exports.findById = function(req, res) {
    // logic to handle GET /cars/
};

exports.create = function(req, res) {
    // logic to handle POST /cars
}

exports.create = function(req, res) {
    // logic to handle PUT /cars/
}

exports.deleteById = function(req, res) {
    // logic to handle DELETE /cars/
}

Now that we have our basic handlers, lets wire them up in app.js.
We can define this just above the http server code

// Car resource routes
var carResource = require('./resource/carres');
app.get('/cars', carResource.findAll);
app.get('/cars/:id', carResource.findById);
app.post('/cars', carResource.create);
app.delete('/cars/:id', carResource.removeById);
app.put('/cars/:id', carResource.update);

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

We have now implemented the basic structure for our REST API.
We can test it, however none of our REST operations return a response.
Let’s quickly write some code to return a 201 status when we POST /cars

In carsres.js, implement the following:

exports.create = function(req, res) {
    // For testing purposes, we are not actually creating anything
    res.send(201); // created
};

Okay, now lets validate that our API is indeed operational.

First, we must start our web server

cd cars_project
node app.js

Next, using curl, let’s formulate a POST request and validate we get a 201 in response:

curl -X -i POST http://localhost:3000/cars

Verify the 201 status response

V. Create a model object to persist and retrieve Cars to and from MongoDB

Let’s create a new folder cars_project/model and a new file cars.js.
The following JavaScript file manipulates our MongoDB. Here we perform our CRUD operations: Create, Retrieve, Update, and Delete.

Please see the code comments included below for a detailed explanation of carres.js.

// export this module, so that it is accessible to our application modules
module.exports = Cars;

// Cars constructor
function Cars() {
        if (!(this instanceof Cars)) {
                return new Cars();
        }

        // require mongodb
        var mongo = require('mongodb');
        // Connect to our mongodb running on localhost and named 'test'
        var db = require('monk')('localhost/test');
        // obtain a reference to our cars collection within mongodb
        this.cars = db.get('cars');
};

// Retrieve a list of all persisted
Cars.prototype.findAll = function(success, error) {
    this.cars.find({},{},response(success, error));
};

// Retrieve a car by its id
Cars.prototype.findById = function(id, success, error) {
        this.cars.findById(id, response(success,error));
};

// Persist a new car document to mongodb
Cars.prototype.create = function(car, success, error) {
        this.cars.insert(car, response(success,error));
};

// Update an existing car document by id in mongodb
Cars.prototype.update = function(car, success, error) {
        this.cars.findAndModify(car._id,
                { $set: { name: car.name } }, response(success, error));
};

// Remove a car by id from the mongodb
Cars.prototype.removeById = function(id, success, error) {
        this.cars.remove({_id : id}, response(success, error));
};

// Callback to the supplied success and error functions
// The caller will supply this function. The callers implementation
// will provide the necessary logic. In the case of the sample app,
// the caller's implementation will send an appropriate http response.
var response = function(success, error) {
        return function(err, doc) {
                if (err) {
                        // an error occurred, call the supplied error function
                        error(err);
                } else {
                        // call the supplied success function
                        success(doc);
                }
        };
}

VI. Wiring the cars model and cars resource
Now that we’ve created a model object for cars, we must update our cars resource such that it can make the appropriate model calls to manipulate documents stored in MongoDB.

Open resources/carsres.js, and make the following modifications:

var cars = require('../db/cars')();

exports.findAll = function(req, res) {
        var ok = function(doc) {
                res.json(doc);
        };
        var err = function(err) {
                res.send(404);
        };
        cars.findAll(ok, err);
};

exports.findById = function(req, res) {
        var ok = function(doc) {
                res.json(doc);
        };
        var err = function(err) {
                res.send(404);
        };
        cars.findById(req.params.id, ok, err);
};

exports.create = function(req, res) {
        var ok = function(doc) {
                res.location('/cars/doc._id');
                res.send(201);
        };
        var err = function(err) {
                res.send(409, "Failed to create car");
        };
        cars.create(req.body, ok, err);
};

exports.update = function(req, res) {
        if (!req.body._id) {
                res.send(404, "id required");
        } else {
                var ok = function(doc) {
                        res.send(200);
                };
                var err = function(err) {
                        res.send(409, "update failed");
                };
                cars.update(req.body, ok, err);
        }
};

exports.removeById = function(req, res) {
                var ok = function(doc) {
                res.send(200);
        };
        var err = function(err) {
                res.send(409, "Failed to remove car");
        };
        cars.removeById(req.params.id, ok, err);

VII. Conclusion

There you have it,  a fully operational RESTful API that persists information to a MongoDB. All of this with minimal code. Cool! Node.js is quite amazing and quite powerful. Impressive!

Thank you!

You may also like...

1 Response

  1. August 14, 2016

    […] Source: Create a REST API with Node.js, Express, and MongoDB | c m d […]

Leave a Reply