Hello friends! Welcome to the 2nd article of the Let's Build a Node.js REST API Series! In this article, we will continue from where we left off in Designing and Planning your API and start creating some routes and controllers for our T-API!
What are controllers?
Controllers are typically callback functions that corresponds to the routers to handle requests. It is a good design principle to keep the code concise and readable. In the previous article, I discussed what a route is. A sample route might look like:
// Syntaxapp.method('<path>', callbackFunction)// Exampleapp.get("/", function (req, res) { res.json({message: "Hello world!"});});
As you add more routes to the API, the script may start to look long and messy like:
(This is just an illustration. No need read this long chunk of code)
app.post('/api/exercise/new-user', function(req, res) { let username = req.body.username; Person.findOne({username:username}, (err,findData)=>{ if (findData == null){ //no user currently, make new const person = new Person({username : username, exercise : []}); person.save((err,data)=>{ if(err){ return res.json({error: err}); } return res.json({"username":findData.username,"id":findData.shortId}); }); }else{ //username taken, show their id return res.json({error:"This username is taken","id":findData.shortId}); } });}app.post('/api/exercise/add', function(req,res){ let id = req.body.userId; let descr = req.body.description; let duration = req.body.duration; let date = req.body.date; if(date != ''){ date = new Date(req.body.date); //save as Date object } if(descr == ''|| duration == '' || id == ''){ return res.json({error: 'missing values'}); } //check if id exists in database Person.findOne({shortId:id}, (err,data)=>{ if (data == null){ return res.json({error: 'id not found'}); }else{ data.exercise = data.exercise.concat({desc : descr, duration: duration, date: date}); //save data.save((err, data) => { if (err) return res.json({error: err}); }); return res.json({"username": data.username, "description": descr, "duration": duration,"id": id, "date": date}); } });}
So a controller can reduce that huge chunk of code into:
app.post('/api/exercise/new-user', UserController.addUser); //new userapp.post('/api/exercise/add', UserController.addExercise); //new exercise
There, much simpler to read. That's the beauty of a controller. The functions are kept in another file (i.e. controllers.js) so that our server.js looks clean! So, let's get started implementing our routes and controllers.
Step 1: Create folders and files
In your project's root directory, create 2 folders and name them 'routes' and 'controllers'.
Then, in each folder, create a 'tea.js' file for our tea route and tea controller. It is a convention to name the controller the same as the route which it is handling. Your directory should look like:
Step 2: The First Route and Controller
Awesome! Now, open your routes/tea.js file. We can create our first route as follows:
- Create an express router object to set up our routes
- Import our tea controller from our controllers/tea.js file we created earlier
- Create our first route with the controller function as the callback to handle the request.
- Export the route to use in our server.js
In code it will look like:
const express = require('express'); //import express// 1.const router = express.Router(); // 2.const teaController = require('../controllers/tea'); // 3.router.post('/tea', teaController.newTea); // 4. module.exports = router; // export to use in server.js
For this example, we are creating POST '/tea' route and set the teaController newTea function to handle the request. At this point, we have not yet created the newTea function but we'll do that right now.
In controllers/tea.js:
// newTea function for post tea routeconst newTea = (req, res, next) => { res.json({message: "POST new tea"}); // dummy function for now};module.exports = {newTea};
In our tea controller, we create the newTea function to handle the POST '/tea' request. For now, it will print a message. Then, we export this function so we can import it to our routes/tea.js, as shown earlier. Great, now your first route and its controller is successfully created! Let's add the routes to the server so that it can access them.
Our server.js from the first article is now updated with 2 lines:
const routes = require('./routes/tea');
to import the routes/tea.js`app.use('/', routes);
to use them via express.
Now, server.js should look like:
const express = require ('express');const routes = require('./routes/tea'); // import the routesconst app = express();app.use(express.json());app.use('/', routes); //to use the routesconst listener = app.listen(process.env.PORT || 3000, () => { console.log('Your app is listening on port ' + listener.address().port)})
Step 3: Testing with POSTman
Alright, so that's the simplest way to write a route and its controller! But now, how do we know it works? In back-end programming, we don't usually have a user interface to test on the browser...
This is where POSTman comes in. It is a great and free tool for testing APIs. To get started, download POSTman here.
Then we run our server.js and run it on port 3000 with node server.js
. Once the server is running, the console should output:
Your app is listening on port 3000
Back in POSTman, enter the url as http://localhost:3000/tea
, set the method to POST and click Send. Refer to the image below.
As shown in the image above, the response of the request outputs the message as intended, which it means it works! Yay! We have successfully made our first route and controller!
Now, we just need to add all the other endpoints for our '/tea' route such as GET and DELETE. As discussed in the previous article, we also have a '/tea/:name' route to GET, POST and DELETE an individual tea object. Let's start adding those too!
Feel free to stop at this step to try writing them yourself. It's the same logic as the first one we wrote.
Please wait, coding in progress...
(Source: data.whicdn.com/images/329890298/original.gif)
Step 4: Create all routes and API endpoints
Here's what the routes/tea.js looks like by the end of this step.
routes/tea.js
const express = require('express');const router = express.Router();const teaController = require('../controllers/tea');router.get('/tea', teaController.getAllTea);router.post('/tea', teaController.newTea);router.delete('/tea', teaController.deleteAllTea);router.get('/tea/:name', teaController.getOneTea);router.post('/tea/:name', teaController.newComment);router.delete('/tea/:name', teaController.deleteOneTea);module.exports = router;
Just like what we did for our POST '/tea' route, we create GET and DELETE '/tea' routes the same way and add the controller functions getAllTea and deleteAllTea to handle the request.
Similarly, we create the GET, POST and DELETE routes for '/tea/:name', with their corresponding controller functions getOneTea, newComment and deleteOneTea. Take your time to read the code to understand it.
Let's take a look at the controller functions for each route. For now, they will all simply return a json message describing what they are intended to do. Take your time to read and understand the functions.
controllers/tea.js
//GET '/tea'const getAllTea = (req, res, next) => { res.json({message: "GET all tea"});};//POST '/tea'const newTea = (req, res, next) => { res.json({message: "POST new tea"});};//DELETE '/tea'const deleteAllTea = (req, res, next) => { res.json({message: "DELETE all tea"});};//GET '/tea/:name'const getOneTea = (req, res, next) => { res.json({message: "GET 1 tea"});};//POST '/tea/:name'const newComment = (req, res, next) => { res.json({message: "POST 1 tea comment"});};//DELETE '/tea/:name'const deleteOneTea = (req, res, next) => { res.json({message: "DELETE 1 tea"});};//export controller functionsmodule.exports = { getAllTea, newTea, deleteAllTea, getOneTea, newComment, deleteOneTea};
Testing what we have so far
Now that we have all our endpoints done, try to test each of them out in POSTman and make sure it returns the correct message.
Note for our '/tea/:name' routes, we can supply a random string as the name parameter. For my example, I will use 'green' as the string so the route would be http://localhost:3000/tea/green
.
Test Summary and Expected Output
URL | HTTP Method | Message Response |
localhost:3000/tea | GET | GET all tea |
localhost:3000/tea | POST | POST new tea |
localhost:3000/tea | DELETE | DELETE all tea |
localhost:3000/tea/green | GET | GET 1 tea |
localhost:3000/tea/green | POST | POST 1 tea comment |
localhost:3000/tea/green | DELETE | DELETE 1 tea |
If you passed all the tests, great! The API is ready for Part 3: Integration with a database.
That's all for now!
We shall continue this API project by building the controller functions and integrating it with MongoDB Atlas in the next article of the series! Thanks for reading and please leave a like or a share if it is helpful. Don't hesitate to ask any questions in the comments below. If there are some concepts you are unsure of, please have a look at some of the reading resources below. Cheers!
Further Reading
- About Routes and Controllers
- A Deep Look into RESTful APIs
- The Basics of HTTP Request Methods
- Intro to Back-end Programming
- Designing and Planning a REST API for beginners
- HTTP Module and Express
FAQs
How to create a REST API using Node js? ›
- Step 1: Install Node.js and NPM. ...
- Step 2: Create a new project folder. ...
- Step 3: Initialize a new Node.js application. ...
- Step 4: Install Express and other dependencies. ...
- Step 5: Import necessary modules. ...
- Step 6: Define a route that listens to requests. ...
- Step 7: Define an endpoint.
- #1 – Use HTTP Methods & API Routes.
- #2 – Use HTTP Status Codes Correctly.
- #3 – Use HTTP headers to Send Metadata.
- #4 – Pick the right framework for your Node. js REST API.
- #5 – Black-Box Test your Node. ...
- #6 – Do JWT-Based, Stateless Authentication.
- #7 – Use Conditional Requests.
- #8 – Embrace Rate Limiting.
Use Express for Node. js to build RESTful APIs. Create and configure middleware to add things like logging, authentication and authorization, and other web development technologies.
How to create controllers in nodejs? ›- Create a folder called controllers .
- Create a file called comments.js and add the following code: ...
- Let's import the controllers on the app.js file; add the following lines after var users = require('./server/routes/users') : ...
- Now add the comments route after app.use('/users', users) :
- Use JSON as the Format for Sending and Receiving Data. ...
- Use Nouns Instead of Verbs in Endpoints. ...
- Name Collections with Plural Nouns. ...
- Use Status Codes in Error Handling. ...
- Use Nesting on Endpoints to Show Relationships. ...
- Use Filtering, Sorting, and Pagination to Retrieve the Data Requested.
REST stands for REpresentational State Transfer. REST is web standards based architecture and uses HTTP Protocol. It revolves around resource where every component is a resource and a resource is accessed by a common interface using HTTP standard methods. REST was first introduced by Roy Fielding in 2000.
Is node JS used for REST API? ›Using these HTTP operations and a resource name as an address, we can build a Node. js REST API by creating an endpoint for each operation. And by implementing the pattern, we will have a stable and easily understandable foundation enabling us to evolve the code rapidly and maintain it afterward.
How do I map a REST API? ›To create an API mapping
Select a custom domain name that you've already created. Choose API mappings. Choose Configure API mappings. Choose Add new mapping.
A route is a combination of an HTTP method, a path, and the function to handle it defined in an application. They help determine which controllers receive certain requests. A controller is a class defined with methods for handling one or more requests. The controller provides the handler function for a route.
How to separate routers and controllers in node js? ›- Approach: We will create a simple Node. ...
- Implementation: Below is the implementation of the above approach.
- Step 1: Initializes NPM: Create and Locate your project folder in the terminal & type the command npm init -y.
What is the difference between a router and a controller? ›
The controller sits between the model and the view. It communicates with both to make a response to a request. The router chooses which controller (and which method on that controller) handles the request.
How do I create a REST API example? ›Under REST API, choose Build. Under Create new API, choose Example API and then choose Import to create the example API. For your first API, the API Gateway console starts with this option as default. You can scroll down the OpenAPI definition for details of this example API before choosing Import.
How to build REST API in node js with MongoDB? ›- Step 1: Connecting to MongoDB Atlas.
- Step 2: Adding REST API CRUD Routes.
- Step 3: Setting Up the Front-End.
- Step 4: Testing the Application.
Step #1 – Enter the URL of the API in the textbox of the tool. Step #2 – Select the HTTP method used for this API (GET, POST, PATCH, etc). Step #3 – Enter any headers if they are required in the Headers textbox. Step #4 – Pass the request body of the API in a key-value pair.