With the release of Express 4 it has gotten even easier to create RESTful APIs. If you are creating a Single Page App you will definitely need a RESTful web service which supports CRUD operations. My last tutorial focussed on creating a Single Page CRUD app with Angular’s $resource. This tutorial explains how to design the backend API for such a CRUD app using Express 4.
Just note that a lot has been changed since Express 3. This tutorial doesn’t explain how to upgrade your app from Express 3 to Express 4. Rather it will cover how to create the API with Express 4 directly. So, let’s get started.
Our app will be a simple movie database which supports basic CRUD operations. We will use Express 4 as the web framework and MongooseJS as the object modeling tool. To store the movie entries we will use MongoDB.
Before going further let’s take a look at what the API will look like:
We will use the following directory structure in our app:
Here are some points about the above directory structure:
bin/www.js
is used to bootstrap our app.models
directory stores our mongoose models. For this app we will have just one file called movie.js
.routes
directory will store all the Express routes.app.js
holds the configurations for our Express app.Finally, node_modules
and package.json
are the usual components of a Node.js app.
To create the API we will use the following modules:
Note – body-parser
is not a part of the Express core anymore. You need to download the module separately. So, we have listed it in the package.json
.
To obtain these packages we will list them as dependencies in our package.json
. Here is our package.json
file:
{
"name": "Movie CRUD API",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"main":"./bin/www",
"engines": {
"node": "0.10.x"
},
"dependencies": {
"express": "~4.2.0",
"body-parser": "~1.0.0",
"mongoose": "~3.8.11"
}
}
Just run npm install
and all the dependencies will be downloaded and placed under the node_modules
directory.
Since we are building an API for a movie database we will create a Movie
model. Create a file named movie.js
and put it in the models
directory. The contents of this file, shown below, create a Mongoose model.
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var movieSchema = new Schema({
title: String,
releaseYear: String,
director: String,
genre: String
});
module.exports = mongoose.model('Movie', movieSchema);
In the previous snippet we create a new model, Movie
. Each movie has four properties associated with it – title, release year, director, and genre. Finally, we put the model in the module.exports
so that we can access it from the outside.
All of our routes go in routes/movies.js
. To start, add the following to your movies.js
file:
var Movie = require('../models/movie');
var express = require('express');
var router = express.Router();
Express 4 has a new method called express.Router()
which gives us a new router
instance. It can be used to define middlewares and routes. The interesting point about Express router
is that it’s just like a mini application. You can define middlewares and routes using this router and then just use it in your main app just like any other middleware by calling app.use()
.
When users send a GET
request to /api/movies
, we should send them a response containing all the movies. Here is the snippet that creates a route for this.
router.route('/movies').get(function(req, res) {
Movie.find(function(err, movies) {
if (err) {
return res.send(err);
}
res.json(movies);
});
});
router.route()
returns a single route instance which can be used to configure one or more HTTP verbs. Here, we want to support a GET
request. So, we call get()
and pass a callback which will be called when a request arrives. Inside the callback we retrieve all the movies using Mongoose and send them back to the client as JSON.
Our API should create a new movie in the database when a POST
request is made to /api/movies
. A JSON string must be sent as the request body. We will use the same route, /movies
, but use the method post()
instead of get()
.
Here is the code:
router.route('/movies').post(function(req, res) {
var movie = new Movie(req.body);
movie.save(function(err) {
if (err) {
return res.send(err);
}
res.send({ message: 'Movie Added' });
});
});
Here, we create a new Movie
instance from the request body. This is where body-parser
is used. Then we just save the new movie and send a response indicating that the operation is successful.
Note that the methods get()
, post()
, etc. return the same route
instance. So, you can in fact chain the previous two calls as shown below.
router.route('/movies')
.get(function(req, res) {
Movie.find(function(err, movies) {
if (err) {
return res.send(err);
}
res.json(movies);
});
})
.post(function(req, res) {
var movie = new Movie(req.body);
movie.save(function(err) {
if (err) {
return res.send(err);
}
res.send({ message: 'Movie Added' });
});
});
If users want to update a movie, they need to send a PUT
request to /api/movies/:id
with a JSON string as the request body. We use the named parameter :id
to access an existing movie. As we are using MongoDB, all of our movies have a unique identifier called _id
. So, we just need to retrieve the parameter :id
and use it to find a particular movie. The code to do this is shown below.
router.route('/movies/:id').put(function(req,res){
Movie.findOne({ _id: req.params.id }, function(err, movie) {
if (err) {
return res.send(err);
}
for (prop in req.body) {
movie[prop] = req.body[prop];
}
// save the movie
movie.save(function(err) {
if (err) {
return res.send(err);
}
res.json({ message: 'Movie updated!' });
});
});
});
Here, we create a new route /movies/:id
and use the method put()
. The invokation of Movie.findOne({ _id: req.params.id })
is used to find the movie whose id
is passed in the URL. Once we have the movie
instance, we update it based on the JSON passed in the request body. Finally, we save this movie
and send a response to the client.
To read a single movie, users need to send a GET
request to the route /api/movies/:id
. We will use the same route as above, but use get()
this time.
router.route('/movies/:id').get(function(req, res) {
Movie.findOne({ _id: req.params.id}, function(err, movie) {
if (err) {
return res.send(err);
}
res.json(movie);
});
});
The rest of the code is pretty straightforward. We retrieve a movie based on the passed id
and send it to the user.
To delete a movie, users should send a DELETE
request to /api/movies/:id
. Again, the route is the same as above, but the method is different (i.e. delete()
).
router.route('/movies/:id').delete(function(req, res) {
Movie.remove({
_id: req.params.id
}, function(err, movie) {
if (err) {
return res.send(err);
}
res.json({ message: 'Successfully deleted' });
});
});
The method Movie.remove()
deletes a movie from the database, and we send a message to the user indicating success.
Now we are all set. But wait! We need to put the router
instance in the module.exports
so that we can use it in our app as a middlewaree. So, this is the last line in the file movies.js
:
module.exports = router;
All our configurations go into app.js
. We start by requiring the necessary modules:
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var movies = require('./routes/movies'); //routes are defined here
var app = express(); //Create the Express app
The next step is connecting to MongoDB via Mongoose:
//connect to our database
//Ideally you will obtain DB details from a config file
var dbName = 'movieDB';
var connectionString = 'mongodb://localhost:27017/' + dbName;
mongoose.connect(connectionString);
Finally, we configure the middleware:
//configure body-parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use('/api', movies); //This is our route middleware
module.exports = app;
As you can see I have used the router
just like any other middleware. I passed /api
as the first argument to app.use()
so that the route middleware is mapped to /api
. So, in the end our API URLs become:
/api/movies
/api/movies/:id
The following code goes into bin/www.js
, which bootstraps our app:
var app = require('../app'); //Require our app
app.set('port', process.env.PORT || 8000);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
By running node bin/www.js
, your API should be up!
Now that we have created the API we should test it to make sure everything works as expected. You can use Postman, a Chrome extension, to test all of your endpoints. Here are a few screenshots that show POST
and GET
requests being tested in Postman.
This was a basic overview of how you can create RESTful APIs easily with Node and Express. If you want to dig deeper into Express be sure to check out their docs. If you want to add or ask something please feel free to comment.
The source code for the app is available for download on GitHub.
**Recommended Courses: **
Learn NodeJS in Hours
☞ http://on.codetrick.net/H1PTldWlM
Supreme NodeJS Course - For Beginners
☞ http://on.codetrick.net/ryg86ldWlM
Node.js et Express.js par la pratique
☞ http://on.codetrick.net/BJ8pg_ZeM
Build a Real Time web app in node.js , Angular.js, mongoDB
☞ https://goo.gl/1ZMTEp
☞ Machine Learning Zero to Hero - Learn Machine Learning from scratch
☞ Learn JavaScript - Become a Zero to Hero
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ What Can We Learn With JavaScript Fatigue
☞ E-Commerce JavaScript Tutorial - Shopping Cart from Scratch