REST API Server with Node (Express) and Mongodb on Heroku

By | 04/07/2015

In the previous post, we created a simple API to add, retrieve, update and delete todo items to a Mongodb database. The issue is that everything is running on localhost, which is good for development purposes but doesn’t bring us far. It would be good to have the server API running somewhere in the cloud. Hence, in this post, I will basically use the application we created back then and run it from Heroku.

To follow along, I suggest to use git clone command to clone the app in your own directory and start from there.

wim@ubuntu:~/Blog$ git clone https://github.com/wiwa1978/blog-express-todo-mongo-api Express_Todo_Mongo_API_Heroku

‘Express_Todo_Mongo_API_Heroku’ is just the directory to which we will clone the repository.

In order to run the application on Heroku, we need to add a Procfile with the following content:

web: node bin/www

Next, we need to create an Heroku application. We choose the name ‘express-todo-api-server’, so our app will be available on https://express-todo-api-server.herokuapp.com

wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ heroku create express-todo-api-server
Creating express-todo-api-server... done, stack is cedar-14
https://express-todo-api-server.herokuapp.com/ | https://git.heroku.com/express-todo-api-server.git

Next, we also will need to have a Mongo database in the cloud. Heroku works with Mongolabs, which is very easy to setup and use. First, add it to the Heroku application.

wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ heroku addons:add mongolab --app express-todo-api-server
Adding mongolab on express-todo-api-server... done, v3 (free)
Welcome to MongoLab.  Your new subscription is being created and will be available shortly.  Please consult the MongoLab Add-on Admin UI to check on its progress.
Use `heroku addons:docs mongolab` to view documentation.

Before we can push the code to Heroku, we need to ensure that we are using this Mongolab connection rather than our local Mongodb installation. In order to do see, change the connection settings in the config/database.js file from:

module.exports = { url : ‘mongodb://localhost/todo’ }

to

module.exports = {
	url : process.env.MONGOLAB_URI
}

Note: don’t put quotes (‘ ‘) around the environment variable!!

I struggled a lot with the default view engine. As we want to create an API service only, we should not define a view engine like Jade. In the app.js file, there is a section like below:

app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

Change this to:

app.use(function(err, req, res, next){
    res.status(err.status || 500);
    res.send({
        message: err.message,
        error: err
    });
    return;
});

What the above does is actually quite simple. Instead of rendering the error view, it will just send back a json message with the error message. I have to admit that I’m still not satified completely as the ideal would be that I don’t have to specify a default template engine at all. In the end, it does not make sense to specify a view template if all we want to do is to expose a REST API. I’ll have a look into this in the future. I consider it less relevant for now as it works perfectly well now…

Deploying to Heroku

I always post the code to Github and then also use Git to deploy to heroku. I’ll give an example on how to do this in below snippet. First I will cover how to upload the code to Github:

wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ echo "# Express_Todo_Mongo_API_Heroku" >> README.md
wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ git init
wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ git add .
wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ git commit -m "First commit"
wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ git remote add origin https://github.com/wiwa1978/blog-express-todo-mongo-api-heroku
wim@ubuntu:~/Blog/Express_Todo_Mongo_API_Heroku$ git push -u origin master

Next, I’ll show how to upload the code to Heroku:

wim@ubuntu:~/Dropbox/Programming/Blog/Express_Todo_Mongo_API_Heroku$ heroku git:remote -a express-todo-api-server
wim@ubuntu:~/Dropbox/Programming/Blog/Express_Todo_Mongo_API_Heroku$ git push heroku master
Counting objects: 1370, done.
Compressing objects: 100% (1251/1251), done.
Writing objects: 100% (1370/1370), 1.99 MiB | 234.00 KiB/s, done.
Total 1370 (delta 152), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Node.js app detected
remote: 
remote: -----> Creating runtime environment
remote:        
remote:        NPM_CONFIG_LOGLEVEL=error
....
remote: -----> Build succeeded!
remote:        ├── body-parser@1.12.4
remote:        ├── cookie-parser@1.3.5
remote:        ├── debug@2.2.0
remote:        ├── express@4.12.4
remote:        ├── jade@1.9.2
remote:        ├── method-override@2.3.3
remote:        ├── mongoose@3.8.31
remote:        ├── morgan@1.5.3
remote:        └── serve-favicon@2.2.1
remote:        
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing... done, 11.6MB
remote: -----> Launching... done, v4
remote:        https://express-todo-api-server.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy.... done.
To https://git.heroku.com/express-todo-api-server.git
 * [new branch]      master -> master

I always check the heroku logs to see if my application is up or if it has crashed.

2015-07-03T15:24:21.530494+00:00 heroku[api]: Release v12 created by wauterw@gmail.com
2015-07-03T15:24:21.840320+00:00 heroku[web.1]: State changed from up to starting
2015-07-03T15:24:23.016169+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2015-07-03T15:24:23.940442+00:00 heroku[web.1]: Process exited with status 143
2015-07-03T15:24:24.279515+00:00 heroku[web.1]: Starting process with command `node bin/www`
2015-07-03T15:24:26.453511+00:00 app[web.1]: Detected 512 MB available memory, 512 MB limit per process (WEB_MEMORY)
2015-07-03T15:24:26.453541+00:00 app[web.1]: Recommending WEB_CONCURRENCY=1
2015-07-03T15:24:27.619823+00:00 app[web.1]: Listening on port 8148
2015-07-03T15:24:28.159017+00:00 heroku[web.1]: State changed from starting to up

The last sentence is what we need to have. Good, seems like everything is running fine. Let’s verify it with POSTMAN, the ultimate REST client.

First, let’s see all todo items. Obviously, we will receive an empty Json body, indicated with []:

1.GetAllItems

Then, let us add a todo item:

2.PostItem

Let’s ensure it has been added successfully:

3.GetAllItens

Why not update the item:

4.Updated

Check if it has been updated successfully:

5.GetItemAfterUpdate

And finally, delete the item again:

6.Deleted

Full source code as it is deployed to Heroku can be found on Github. Should be ready for you guys to clone and test it. Obviously, use your own Heroku environment to test out things. I’m using https://express-todo-api-server.herokuapp.com/ on Heroku.