Creating RESTful APIs with NodeJS and MongoDB Tutorial (Part II)

Welcome to this tutorial about RESTful API using Node.js (Express.js) and MongoDB (mongoose)! We are going to learn how to install and use each component individually and then proceed to create a RESTful API.

What is a RESTful API?

REST stands for Representational State Transfer. It is an architecture that allows client-server communication through a uniform interface. REST is stateless, cachable and has property called idempotence. It means that the side effect of identical requests have the same side-effect as a single request.

Installing the MEAN Stack Backend

In this section, we are going to install the backend components of the MEAN stack: MongoDB, NodeJS and ExpressJS. If you already are familiar with them, then jump to wiring the stack. Otherwise, enjoy the ride!

Installing NodeJS

The Node official definition is:

Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

Middlewares are pluggable processors that runs on each request made to the server. You can have any number of middlewares that will process the request one by one in a serial fashion. Some middlewares might alter the request input. Others, might create log outputs, add data and pass it to the next() middleware in the chain.

We can use the middlewares using app.use. That will apply for all request. If you want to be more specific, you can use app.verb. For instance: app.get, app.delete, app.post, app.update, …

res: is the response object where we can send the reply back to the client.

next: continue with the next middleware in the chain.

You can also specify a path that you want the middleware to activate on.

Middleware mounted on "/todos/:id" and log the request method

1

2

3

4

app.use('/todos/:id', function (req, res, next) {

console.log('Request Type:', req.method);

next();

});

And finally you can use app.get to catch GET requests with matching routes, reply the request with a response.send and end the middleware chain. Let’s use what we learned on mongoose read to reply with the user’s data that matches the id.

Middleware mounted on "/todos/:id" and returns

1

2

3

4

5

6

app.get('/todos/:id', function (req, res, next) {

Todo.findById(req.params.id, function(err, todo){

if(err) res.send(err);

res.json(todo);

});

});

Notice that all previous middlewares called next() except this last one, because it sends a response (in JSON) to the client with the requested todo data.

Hopefully, you don’t have to develop a bunch of middlewares besides routes, since ExpressJS has a bunch of middlewares available.

errorhandler: Aid development, by sending full error stack traces to the client when an error occurs. app.use(errorhandler()). It is good practice to surround it with an if statement to check process.env.NODE_ENV === 'development'.

vhost: Allows you to use different stack of middlewares depending on the request hostname. e.g. app.use(vhost('*.user.local', userapp)) and app.use(vhost('assets-*.example.com', staticapp)) where userapp and staticapp are different express instances with different middlewares.

timeout: halt execution if it takes more that a given time. e.g. app.use(timeout('5s'));. However you need to check by yourself under every request with a middleware that checks if (!req.timedout) next();.

Wiring up the MEAN Stack

In the next sections, we are going to put together everything that we learn from and build an API. They can be consume by browsers, mobile apps and even other servers.

Bootstrapping ExpressJS

After a detour in the land of Node, MongoDB, Mongoose, and middlewares, we are back to our express todoApp. This time to create the routes and finalize our RESTful API.

Express has a separate package called express-generator, which can help us to get started with out API.

Install and run "express-generator"

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

# install it globally using -g

npm install express-generator -g

# create todo-app API with EJS views (instead the default Jade)

express todo-api -e

# create : todo-api

# create : todo-api/package.json

# create : todo-api/app.js

# create : todo-api/public

# create : todo-api/public/javascripts

# create : todo-api/routes

# create : todo-api/routes/index.js

# create : todo-api/routes/users.js

# create : todo-api/public/stylesheets

# create : todo-api/public/stylesheets/style.css

# create : todo-api/views

# create : todo-api/views/index.ejs

# create : todo-api/views/layout.ejs

# create : todo-api/views/error.ejs

# create : todo-api/public/images

# create : todo-api/bin

# create : todo-api/bin/www

#

# install dependencies:

# $ cd todo-api && npm install

#

# run the app:

# $ DEBUG=todo-app:* npm start

This will create a new folder called todo-api. Let’s go ahead and install the dependencies and run the app:

1

2

3

4

5

# install dependencies

cd todo-api && npm install

# run the app

PORT=4000 npm start

Use your browser to go to http://0.0.0.0:4000, and you should see a message “Welcome to Express”

Connect ExpressJS to MongoDB

In this section we are going to access MongoDB using our newly created express app. Hopefully, you have installed MongoDB in the setup section, and you can start it by typing (if you haven’t yet):

1

mongod

Install the MongoDB driver for NodeJS called mongoose:

1

npm install mongoose --save

Notice --save. It will add it to the todo-api/package.json

Next, you need to require mongoose in the todo-api/app.js

Add to app.js

1

2

3

4

5

6

7

8

9

10

// load mongoose package

var mongoose = require('mongoose');

// Use native Node promises

mongoose.Promise = global.Promise;

// connect to MongoDB

mongoose.connect('mongodb://localhost/todo-api')

.then(() =>console.log('connection succesful'))

.catch((err) =>console.error(err));

Now, When you run npm start or ./bin/www, you will notice the message connection successful. Great!

You can find the repository here and the diff code at this point:
diff

Creating the Todo model with Mongoose

It’s show time! All the above was setup and preparation for this moment. Let bring the API to life.

What’s going on up there? Isn’t MongoDB suppose to be schemaless? Well, it is schemaless and very flexible indeed. However, very often we want bring sanity to our API/WebApp through validations and enforcing a schema to keep a consistent structure. Mongoose does that for us, which is nice.

You can use the following types:

String

Boolean

Date

Array

Number

ObjectId

Mixed

Buffer

API clients (Browser, Postman and curl)

I know you have not created any route yet. However, in the next sections you will. These are just three ways to retrieve, change and delete data from your future API.

Curl

Browser and Postman

If you open your browser and type localhost:3000/todos you will see all the tasks (when you implement it). However, you cannot do post commands by default. For further testing let’s use a Chrome plugin called Postman. It allows you to use all the HTTP VERBS easily and check x-www-form-urlencoded for adding parameters.

Don’t forget to check x-www-form-urlencoded or it won’t work ;)

Websites and Mobile Apps

Probably these are the main consumers of APIs. You can interact with RESTful APIs using jQuery’s $ajax and its wrappers, BackboneJS’s Collections/models, AngularJS’s $http or $resource, among many other libraries/frameworks and mobile clients.

In the end, we are going to explain how to use AngularJS to interact with this API.

ExpressJS Routes

To sum up we want to achieve the following:

Resource (URI)

POST (create)

GET (read)

PUT (update)

DELETE (destroy)

/todos

create new task

list tasks

error

error

/todos/:id

error

show task :id

update task :id

destroy task ID 1

Let’s setup the routes

Create a new route called `todos.js` in the `routes` folder or rename `users.js`

1

mv routes/users.js routes/todos.js

In app.js add new todos route, or just replace ./routes/users for ./routes/todos

Is it working? Cool, you are done then!
Is NOT working? take a look at the full repository.

What’s next?

Connecting AngularJS with this endpoint. Check out the third tutorial in this series.

Adrian Mejia is a full-stack web developer working at Cisco in Boston. Currently working at Cisco as a Software Engineer. Adrian enjoys writing books and posts about programming, technologies and nerdy stuff. Find our more here.