Published: May 12, 2020, Edited by: Jakob Hastrup

How to create a RESTful API with Node.js

Why?

This guide is made by a student at Roskilde University. He experienced a high learning curve when entering computer science and one of the topics that was hard to understand was the relationship between frontend and backend development. This is also called client-side/server-side programming. A typical tool for linking the frontend with the backend is an Application Programmable Interface (API).

In this guide we will focus on how to create an API with Node.js. By doing this we hopefully ease the learning curve of working with this kind of software. Because there is a lot of hardcore guides in this topic, but many of those expects that you know what an Object Relational Manager (ORM) is, how to build a Node.js project and other details explained in this guide.

Many companies and organisations make APIs to make it possible for developers to make software on their data, without needing direct access to the database. This guide will be a little demanding if you have never programmed, but I have tried to keep it simple. Therefore we build the API locally and use a database I have created. This means that you can meet other people's data when testing.

Just to clarify what an API is, I have a little analogy. The analogy for an API is the waiter at a restaurant. The hungry customer is the homepage and the kitchen is the database. There can be many kinds of customers with different wishes, and the kitchen got different kinds of resources to meet those wishes. A good waiter knows how to communicate the possibilities of the kitchen to the customer and can talk with all kinds of customers. A good API communicates what it’s able to request and can talk with all programming languages. Therefore most APIs are built on the HTTP request and responses with well known dataobjects like JSON. If you don't know what this is, I made a guide about how to use APIs in client-side programming: Introduction to using APIs.

In this guide we will create an API and not just use one. We will implement different types of requests to make it possible to create and read information in the database via the API. This is called CRUD and is actually implemented through the HTTP equivalents POST, GET, PUT and DELETE. In this guide we will only POST and GET, but I will make a PUT and DELETE guide later on.

This is an advanced guide but after doing it you will have a lot of useful skills. And if you’re a Humtek student that aims for computer science I promise, that you will have an easier time as a master student :). We don’t use the exact same tools as the RAWDATA course, but the concepts are exactly the same.

This guide is heavily inspired by Adnan Rahić guide on the topic. I just try to explain the same code with easier language and also found one bug in his code (that is fixed in my version).

RESTful API design with Node.js by Adnan Rahić

This is the code we will make in this tutorial. Use it as debugging tool, you will learn more if you write it yourself.
https://github.com/FablabRUC/apiproject

Prerequisites

To follow this guide we expect that you have programmed before. We also expect that you know what using the terminal means. If you don't its a way to communicate with your computer through command lines. We will show which commands to do, but you need to open the terminal yourself.

We will write the API with the Javascript language and knowledge about the syntax of this language can be helpful especially for troubleshooting. To follow along I recommend to write you program in software similiar to Visual Studio Code. We need to structure the code in subfolders and different files to not confuse ourselves. I think Visual Studio Code is helping us do this while coding.

Download Visual Studio Code here

Create a local Node.js server

To make an API we need to host a server. In this guide we do it locally, but it's possible to do the same thing on a web server (but that's another guide). This part of the guide is inspired by this guide written by Adnan Rahić. I recommend it if you think I'm not explaining the details you want.

You can implement an API by doing everything yourself, but we are lazy and use libraries. A great tool for creating a web based system and adding libraries to it is Node.js. It’s not intuitive because it's controlled through your computer's terminal. But after building several web based applications I have learned that it's worth the effort to learn Node.js.

Download and install Node.js.

Download Node.js here

When you have installed Node.js open your terminal and navigate to a folder directory that you remember. I use the desktop:

cd C:\Users\user\desktop  

In this directory you can write:

mkdir apiproject  
cd apiproject  

This creates a folder on your desktop called apiproject. This folder should be initialized as a Node.js program. This is done like this (in the terminal):

npm init  

npm means node package manager. So the program is actually just initialize the folder to be able to use the structure of a Node.js project.

This command creates a package.json file in your apiproject folder. When you do this the terminal will ask you a bunch of questions. Just press enter besides when it asks for the entry point (index.js), here you write:

 app.js

The result should look like this:

{
  "name": "apiproject",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Is this OK? (yes)  

Press enter and check your folder apiproject. If a package.json file was created you now have a node.js project.

Dependencies

We still need to install dependencies for the project. We will use the libraries express.js, mongoose.js and body-parser.js. This is done like this (in the terminal):

npm install express --save  
npm install mongoose --save  
npm install body-parser --save  

Express is a web framework that we use to create the server. Mongoose is an Object Relational Mapper (ORM) used for working with MongoDB. As this project's data is on a database with MongoDB this is a good choice. Body-parser is a middleware tool used for parsing the data in the HTTP requests. I will explain the different purposes of those tools when we use them. Now it's time for programming. I use visual studio code, but you’re free to use other text editors. But get one with a folder view inside, you won’t regret it.

In the folder apiproject create a file called app.js. In this file write:

// app.js
var express = require('express');  
var app = express();  
module.exports = app;  

The first variable express uses the method require() to import the express module from the node_module folder, which was created when we installed the express module.
Then we make a app variable that equals the method express() and export that app module to the rest of our program. This is good programming practice, because we separate the logic from the application configuration/dependencies.
Therefore create a new file called server.js
In this write:

// server.js
var app = require('./app');  
var port = process.env.PORT || 3000;  
var server = app.listen(port, function() {  
  console.log('Express server listening on port ' + port);
});

This means that we require the app.js, make the port of the server equal to 3000 and make the app listen to this port. Then we print to console that the express server is listening on the port. This is only possible because of our installation of express. Now we need to test if we did everything right. You do this by typing in terminal (still in your apiproject folder):

node server.js  

Then you should see the line from the console.log method: Express server listening on port 3000. If this doesn't work you might have forgotten to save your new files.

The server is running until you close your terminal. We are now ready to connect the server to the database.

Connect to fablabs database

I have made a database you can use for this guide. If you want to make your own database for a project i recommend this page: https://www.mongodb.com/. Its free to make one 500 mb instance with multiple shards (that means backups). But for now just use our database. The database only contains information added by other people who followed this guide. So it’s just a test database.

Connect the ORM to the database

Create a new file in your project folder called db.js. Write in this file:

// db.js
var mongoose = require('mongoose');

mongoose.connect('mongodb+srv://testuser:test@fablabructest-onrwv.mongodb.net/test?retryWrites=true&w=majority',  
{   useNewUrlParser: true,
    useUnifiedTopology: true
});

This makes our mongoose ORM connect to the database. If you created your own database, this is where you need to type the link to your database.
Other database types like SQL has other ORM tools, with other syntax. Unfortunately we will not learn about all the options in this guide. Because there is too many :)

After creating the db.js we need to let the app.js know that it exists. So in app.js add:

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

Understand the Object Relational Mapping

The Object Relational Mapping is used to get data from the database and relate this data to the object-oriented way of describing data. Databases are storing information in relational models. That means tables with simple data like integers and strings. There are no possibilities of methods and storage of objects in the relational models. Therefore we want to convert the data from the database into objects. To illustrate, the database represents its users like:

The object-oriented approach is:

class User {  
    constructor(name, age, email) {
        this.name = name;
        this.age = age;
        this.email = email;
}
}

User user1 = new User(user1, 23, monkey@ruc.dk);  
User user2 = new User(user2, 25, chicken@ruc.dk);  
User user3 = new User(user3, 53, dolphin@ruc.dk);  

The dataschema User.js

Mongoose can make the translation for us, and that's why it's an ORM. We do this by making a folder called user. In this folder we create a file called User.js. The file will represent our data schema and what we expect to create, read, update and delete in the database later on. For this example we stick with creating users so we write this code:

// User.js
var mongoose = require('mongoose');  
var UserSchema = new mongoose.Schema({  
  name: String,
  email: String,
  age: String
});
mongoose.model('User', UserSchema);  
module.exports = mongoose.model('User');  

This code snippet requires mongoose and creates a dataschema. This schema consists of our user parameters. This schema is passed into a datamodel named User. This is all that's needed for mongoose to know what we mean by User objects. We then export this model to the rest of the program. This is important because files don’t automatically know each other.

Now we are finally ready to create the actual API.

Create the CRUD routes

We do this with creating a UserController.js in the user folder:

// UserController.js
var express = require('express');  
var router = express.Router();  
var bodyParser = require('body-parser');  
router.use(bodyParser.urlencoded({ extended: true }));  
router.use(bodyParser.json());  
var User = require('./User');  

Here we require the server and create a router. The router makes your life easier, if you need to restructure the code later on and the body-parser makes the data easier to send through a HTTP request.

The important thing here is that we require the User from our ./User folder. This is possible because of our export in the User.js file. So because of the User.js file the UserController.js also knows what a User model is. Add the UserController.js to the app.js with require and make the app .use() it. The final app.js should look like this:

// app.js
var express = require('express');  
var app = express();  
var db = require('./db');

var UserController = require('./user/UserController');  
app.use('/users', UserController);  
module.exports = app;  

This app.use() is changing the route to access the user controller. In the user controller it was '/', but the app.js now changes it to '/users'. This makes it very easy to change the routes later on. You just need to change the name in the app, and all your routes for different user related action will change.
And now the real magic can be done.

POST

We will create a POST method for our API with this code (still in the UserController.js):

// CREATES A NEW USER
router.post('/', function (req, res) {  
    User.create({
            name : req.body.name,
            email : req.body.email,
            age : req.body.age
        }, 
        function (err, user) {
            if (err) return res.status(500).send("There was a problem adding the information to the database.");
            res.status(200).send(user);
        });
});

This means that when our system is called with a POST HTTP request a User is created. The request can be with a name, email and age. Don’t test it yet, we didn’t export the controller yet.

GET

The GET method is written like this:

// RETURNS ALL THE USERS IN THE DATABASE
router.get('/', function (req, res) {  
    User.find({}, function (err, users) {
        if (err) return res.status(500).send("There was a problem finding the users.");
        res.status(200).send(users);
    });
});

This GET method will return all the Users from the database. This is because no parameters are passed to the find method. We export this code to the application:

module.exports = router;  

Now we are ready to test those two methods.

Test the system

To test the system you need to install another software. This is called postman. This is software for API development, but we just use it for testing the software. Think of it as the client side software. It is able to make HTTP requests and show the response. Download and install Postman.

Download Postman here

Run your server in terminal (from your apiproject folder):

node server.js  

Now you should be able to send a HTTP request with postman. POST is creating new data in the database. GET is receiving what's already there. So try to:

  1. Open postman

  2. Create an account

  3. Login

  4. Press “+”

  5. Choose POST

  6. Enter request url: http://localhost:3000/users

  7. Choose body and choose x-www-form-urlencoded

  8. Insert the keys from our user model: name, email and age

  9. Insert values

  10. Press send

  11. Change the HTTP request to GET and press send again to retrieve what you just POSTed.

  12. If you want to make sure that the user model is actually working try to POST a key that's not in the user model. It should only send the data described in the user model.

If the GET and POST worked as expected you have created an API. You made it possible for Postman to communicate with a MongoDB database. Or you made a client communicate with a server. Every client with the ability of sending http request is able to do what Postman did. This is the essence of RESTful APIs. Your client and server dont speak the same language, but the API is making the communication easy and all the client needs is the URL for the HTTP request.
This implementation is only useful for getting to know the concept API. But there is a lot of functionality that can be implemented with this concept. We will do some of it in the next part of the tutorial with DELETE and PUT. We will also implement a GET that is called with a search term. But you just learned the basics of creating an API and that is to create the right dataobjects and create a CRUD pattern for the needed use. This CRUD pattern needs refinement in our current application to be useful, but that's enough material for another guide. Which i will make as soon as possible.

The final code is available here:

If you want to test this you need to initialize it as a node.js project. This is explained in the part Create a local Node.js server
https://github.com/FablabRUC/apiproject