Nodejs is a remarkable technology for the fulfilling and developing web applications. Being open source and in the past few years, we have seen it rising. It might be a bit different from other traditional web technologies in terms of learning curve but I urge you to stick with it if you are getting in to web development and have opted Node.js ecosystem. In this tutorial, I will walk you through the basics of REST API design with using Node.js ecosystem.
What is REST?
REST is an acronym for Representation State Transfer and is an industry standard (till Graphql conquers the world) for defining how an API and its endpoint (routes) should communicate with the server code of your web application. A REST API consumes HTTP methods such GET, POST, etc. with endpoints that are nothing but URLs that you can use to fetch some data or update/create new data in the database. In his whitepaper, Roy Fielding described the paradigms and practical use of REST. I am going to summarise points what he exactly says in that paper. The basis of a RESTful API depends on below:
To read about them in detail, please see Roy Fielding’s paper on the same here.
Applications that make use of REST APIs perform four basic operations that are known as CRUD.
C: Creating data
R: Reading data
U: Updating data
D: Deleting/removing data
There are some things we need to go through this tutorial successfully.
Access to MongoDB, a NoSQL database on your local machine or cloud
Postman, a REST client to test our API’s endpoints
If you do not have MongoDB installed on your local mahcine, do not worry. In the next step I am going walk you through setting up a free tier of MongoDB in cloud.
Consuming MongoDB in Cloud
For the sake of brevity, I am going to use MongoDB Atlas a service that you can use to store data for your sample application. You can also use other popular database-as-a-service Mlab without any hassle.
I already have an account setup, so I’d suggest you to sign up on mongodb atlas’ site with your email. Once you have logged in, you will get the below screen:
At this point, you can either take time to explore what MongoDB Atlas is or you can skip and together we will setup a Sandbox for our sample application. Click on the “New Project” button on the right side of the web page.
Then you will be prompted to fill in the details. See screenshots below, enter a name for your project and click “next” and then click “Create Project”. Per one account in MongoDB Atlas, you will get one free tier/cluster. Follow the steps below to setup one.
Click on the Build new Cluster button.
Scroll down a bit, and then select the free tier M0. Per free cluster, we get 512mb of space. More than enough for what we need for this tutorial.
Then enter username and password for an Admin connection that we will use to connect to our database through our application. Make sure you remember both username and password and password must a bit strong. Lastly, click on confirm and deploy and the service will take at least 10 minutes to setup a database cluster.
That’s it. The database is now ready to be used. Now let us setup our application.
Configuring Server Side
From your terminal:
Mongoose is client that helps us connect and communicate with our database. BodyParser is needed as a middleware to parse the data to be sent through HTTP requests. Express is de facto standard and is one of the reason we will be using it.
Running the Server
Let’s first the nitty gritties of our server. Create a file app.js in the root directory with the following code:
The app is an object provided by Express API for the developer to communicate with the application and bootstrap a server. In Express application, it is that easy to write bare minimum server. There are different ways you can setup your server but the basics will remain same. For brevity, I am using app.js but you can take a look at Express generator that scaffolds a structrue in a quick manner.
Now, add an npm script to package.json file to test and start our server.
npm run start or
npm start and you should see the success message without any error.
Setting up Mongoose
Mongoose is an ORM (Object Relational Mapper) that is used to interact with MongoDB database instance. We have already setup our instance using MongoDB atlas and installed mongoose as the project dependnecy. So let us start by defining a schema. Though, NoSQL database are schema less it is consider a best practice to define a schema to give some structure to the data that will be stored in our database.
A typical Express application follows MVC (model-view-controller) model to define a directory structure and that is what we are going to do. Create a direcotry
models and inside it a file
Task.js with following code:
This schema does look like a JSON data and that is exactly what MongoDB stores or it appears to be for the developer to. Original format of data stored in MongoDB is called BSON (stands for _Binary JSON) and it converts JSON to BSON is handled by the dtabase itself. You can read more about it here in the official docs.
Mongoose allows us to create define a schema for our the document to be stored in our application via inside the application just by defining a model. You can think it of as a blueprint. All your tasks in the database collection, will have
createdOn value. Lastly, we bind our schema with the name of our collection
Tasks. The collection in MongoDB our by default plural since they tend to contain a number of documents.
createOn are called fields in terms of MongodB terminology. Together they constitute a document inside the collection
Tasks and each document will have a unique ID to identify them as a record in the database. This unique ID is stored in MongoDB database by default and is a 12 byte value made up of different things related to our database. You can read more about how this unique ID created by the database here.
Connecting Database To our Application
Before we further go with the controller part, let us first connect the database to our server and see if everything is working A-OK.
I like to store all my application’s configuration in a
config directory. Create a
db.js file inside that directory.
To get the connection string you have to follow the following steps:
First click on the connect button on your MongoDB Atlas page the following screen will prompt.
Then, click “Allow Access from Anywhere” to white list our server URL.
Then, copy the URI string for version 3.4:
And enter the username and password you entered during the setup of our instance in place of
username:<password> and remove the placeholders
<>. I am using options variable to spike your curisoity such that you will explore about it and the power of mongoose. You can read more about connection options that provided by mongoose here.
Lastly, we use
mongoose.connect() to establish a connection between server and the database instance and handle it gracefully using a promise. But wait, the connection won't be establish unil we connect this config file with our application and for that we need to require this file in our main app.js file.
Now restart our server from command line and you will see the success prompt:
Do you notice one thing here? For every change we make in our application, we have to restart our server from command line and to ignore this tedious process we can make use of a powerful utility called
nodemon developed by Remy Sharp.
After we setup
nodemon I promise we will be focusing on code of our API but making use of this utility will save tons of amount of time when working on an API yourself. Let's install nodemon as a dev dependency first.
After installing it, chnage the
start script in
package.json file to:
Now if we start our server, nodmon will monitor for any changes made and restart the server when necessary on its own. We don’t have to worry about that anymore.
Back to our API code.
Setting up Business Logic
To setup routes or endpoints of our application, we need to include
body-parser in our
BodyParser parses incoming HTTP requests as middleware under
req.bodybefore routes or API have access to them and perform any further actions on them. Very useful and essential step when using forms in a web application.
To define the business logic of our APIs endpoints, we are going to create a separate file
TaskController.js under directory
For our API routes (I am going to call them route for brevity but they are same as endpoints) we are going to five different actions or operations or way to handle incoming requests. These tasks will cover our CRUD operations. Each route will have at least two parameters:
req: request, usefull when creating or or updating a new task and read data from the body (this where BodyParser works like a charm).
res: response to fulfill that incoming request with response.
This completes our controller. The controller is the business logic that binds our endpoints/routes that we are going to define soon to what action or operation they will perform on an incoming request.
Each of the above operation when sending a response does send HTTP status code which clearly determines whether the incoming request was fulfilled or was there an error. This the part of REST paradigm and is best practice. You can read more about this here.
Setting up Routes
We setup our API’s endpoints by first requiring the controller and then passing on a specific endpoint it using the correct HTTP method. The enpoints can be elaborated as:
POST /tasksto create a new task
GET /tasksto get a list of all tasks
GET /tasks/:taskidto get a specific task by its unique id(the one mongodb creates for us)
PUT /tasks/:taskidto modify existing task
DELETE /tasks/:taskidto delete an existing task from our database instance
As a best practice, APIs routes should always use nouns for identifying resource.
Now let us test our API routes using Postman.
Testing our API
Open postman and type
http://localhost:3301/tasks and selct the
POSTmethod. We will first use the POST request to create a new task since our database is currently empty and does not have any data. Use
body to fill in the data which follows same schema we defined in our model.
Hitting the send button should respond with
200 status and the data we created structured exactly like our schema in JSON format.
Similarly, we can test other endpoints of our API. Such as getting all tasks (so far we have so it will give only one task that we just created):
Getting the task by its
Try updating the task or removing it by using the endpoints we defined earlier and changing the HTTP method from Postman yourself.
Hope you learned something valuable by reading this article.
You can find the complete code at this Github repository.