Today in this blog we will leard what are routes in node.js application and understand how we can efficiently use them. How routes help us to write modularized code.
Contents
What are routes in node.js ?
Routes in node.js are used to accept HTTP requests and respond to the requests. Each route defines an unique URI in the application server representing an REST API endpoint. Each endpoint serves a specific purpose. For example, when we want to handle users, we would like to list all users, get details for a specific user when the user ID is provided, create a user, modify a user details and delete a user. We would like to have an endpoint for each. Each operation is a specific task for the application and each of them corresponds to HTTP methods GET, POST, PUT, DELETE.
How to create routes in node.js ?
There are two ways to create REST APIs Today we will see which approach is better.
The first option is, using the methods of the Express app, that corresponds to the HTTP methods. e.g. app.get() app.post() app.patch() app.delete(), app.put() etc. see the Express documentation on the methods on app objects for a full list.
An example using the Express app object is shown below. At first we are creating the app object which represents the express application server. Then we are defining two routes to fetch a user details and create a user. Similarly, we are defining two routes to fetch an order details and create an order. At the end we start listening in the 5000 port. The request.params.id is used to read the URL parameter from the request object.
const express = require('express');
const app = express();
const port = 5000;
app.get('/user/:id', (request, response) => {
response.send('Hello World From User Get ' + request.params.id);
});
app.post('/user/:id', function(request, response) {
response.send('Hello World From User Post ' + request.params.id);
});
app.get('/order/:id', (request, response) => {
response.send('Hello World From Order Get ' + request.params.id);
});
app.post('/order/:id', function(request, response) {
response.send('Hello World From Order Post ' + request.params.id);
});
app.listen(port, () => {
console.log(`My app listening at http://localhost:${port}`);
});
The second option is, using the Router object present in Express. Router acts as a middleware in the application itself. The details of the router can be found in the Express documentation as well.
An example using Router in express is shown here. This code does the same job as the previous example but here we are using a Router object from Express. Don't forget to pay attention to the line app.use(router) . Here we tell the application to use the router we have created.
const express = require('express');
const app = express();
const port = 5000;
const router = require('express').Router();
router.get('/user/:id', (request, response) => {
response.send('Hello World From User Get ' + request.params.id);
});
router.post('/user/:id', function(request, response) {
response.send('Hello World From User Post ' + request.params.id);
});
router.get('/order/:id', (request, response) => {
response.send('Hello World From Order Get ' + request.params.id);
});
router.post('/order/:id', function(request, response) {
response.send('Hello World From Order Post ' + request.params.id);
});
app.use(router);
app.listen(port, () => {
console.log(`My app listening at http://localhost:${port}`);
});
Which approach is better ?
Since we can only instantiate one app variable in our application, all routes created using the first approach have to be present in one file where we instantiate the application server. The file will become bigger if there are lots of APIs. Also, there could be more code when the application becomes complex. For example, a couple of app.use() methods for body-paser authentication mechanism used etc.
In the second approach we can separate the code that is responsible to handle different API routes from the code that instantiates the server. For example, here I have written the example using router using a modular approach
First we create a folder named “routers”. Under routers we create a file user.js and shift the code related to user handling.
const router = require('express').Router();
module.exports = function () {
router.get('/user/:id', (request, response) => {
response.send('Hello World From User Get ' + request.params.id);
});
router.post('/user/:id', function(request, response) {
response.send('Hello World From User Post ' + request.params.id);
});
return router;
}
Then in that folder we create another file order.js and move the code that handles requests related to orders.
const router = require('express').Router();
module.exports = function () {
router.get('/order/:id', (request, response) => {
response.send('Hello World From Order Get ' + request.params.id);
});
router.post('/order/:id', function(request, response) {
response.send('Hello World From Order Post ' + request.params.id);
});
return router;
}
The app.js contains the application server only and makes use of the two routes.
const express = require('express');
const app = express();
const port = 5000;
const userRouter = require('./routers/user.js')();
const orderRouter = require('./routers/order.js')();
app.use(userRouter);
app.use(orderRouter);
app.listen(port, () => {
console.log(`My app listening at http://localhost:${port}`);
});
As a router behaves like a middleware by itself, we can use it as an argument to app.use() . Also, we can use it as an argument to another router’s use() method. In this way we can have more than one route objects each with a specific behaviour responsible for specific routes for the APIs. For example, we can write the above code as below. Then each time we don't have to add /user and /order. Notice that in the router.get() and router.post() we are not adding the “/user” each time. Instead we have mentioned it once in the app.use(). This means all requests starting with /user will be handled by the userRouter.
In routers/user.js
const router = require('express').Router();
module.exports = function () {
router.get('/:id', (request, response) => {
response.send('Hello World From Order Get ' + request.params.id);
});
router.post('/:id', function(request, response) {
response.send('Hello World From Order Post ' + request.params.id);
});
return router;
}
In app.js
const express = require('express');
const app = express();
const port = 5000;
const userRouter = require('./routers/user.js')();
app.use('/user', userRouter);
app.listen(port, () => {
console.log(`My app listening at http://localhost:${port}`);
});
We can also use router.param() to work on parameters before the control comes to the particular route. It will work like a request pre-processing mechanism for parameters. We can do parameter validation too.
You can find the details router parameter handling in the documentation.
Today we have learned what are routes in node.js and how we can efficiently use them.
Comments