We have given so many useful inputs on Node.js and its benefits in developers’ perspective in many of our blogs. Today, it takes a turn and we will be talking about Node.js Middleware and Express Middleware, explicitly.

Node.js is a popular web app framework that does not require any basic introduction. Yet, for readers’ benefit, here are some ravishing advantages that Node.js can bring to developers.

Node.js offers easy scalability of features and functions along with an easy-to-learn education curve to new and experienced developers as well. Therefore it has become very easy for businesses to make the maximum use of Node js Development services and achieve maximum quality outcomes from it.

It gives developers complete freedom and privilege to develop high-performing dynamic web apps. It benefits you by providing caching and comes with great and huge community support. Therefore Adept Developers at eSparkBiz too prefer Nodejs as their first choice for Development purpose.

Express.js For Enterprise Apps plays an important role in tracking and preventing users from performing any specific action or recording the path of every incoming request you receive if you require it.

This is one Node JS Middleware Example, and it makes it possible with a customized Express.JS middleware. Middleware functions are essential to deal with common functionality in web applications you develop, in an elegant manner.

From this blog, Our adept developers have shared their knowledge to help you understand what Middleware in Node JS is and how to create Middleware in Node JS.

Step By Step Guide To Create Node.js Middleware & Express Middleware in 2024

How does Node.js Middleware work?

How-Node-Middleware-Works

Middleware comes in the middle of request and response cycles of Node.js execution. Many leading companies decided to hire node js experts so that helps you to create this solution with ease.

It has access to several functionalities such as to request and response objects and the Next function of the request-response life cycle. Various tasks are performed by Middleware functions, such as:

  • Effectively execute any sort of code.
  • Make quick changes to the request and response objects.
  • Automatically terminate the request-response cycle.
  • Call the next middleware immediately available in the stack.

In case the active middleware function does not stop the request-response cycle, it calls for next () to pass on the control to the consecutive middleware function, to make sure that no requests are hanging.

What is next()?

Understanding-next()-Function

Next() is a middleware function that calls the control of another function once the middleware code is accomplished.

Hence, you can wait until network operations complete prior to proceeding with the further step. Similar to the functionality of route Handlers, a middleware ensures the receipt of the Request and Response objects, effortlessly.

Here, the request object commonly referred to as the variable (req) and the response object referred to as the variable (res).

The next middleware function, which is referred to as the variable ‘next’ plays a responsible role in creating the request-response cycle of the application.

Take a look over the vital tasks performed by the middleware functions.

  • Code execution
  • Make necessary changes to the request and response objects accordingly
  • Completing the request-response cycle
  • Calling the upcoming or subsequent middleware function in the stack

It is necessary that you do not leave the request hanging in your queue if there is no automatic end for the request-response cycle of the current middleware function.

Creating your own Node.js Middleware

We have seen the working of Node.js Architecture at the beginning of our blog. Let us see how to create your own Node.js Middleware with some good examples for better understanding.

With Node.js Middleware, you can run any kind of code and modify the request and response objects, stop any on-going request-response cycle and call the next middleware in the stack automatically when one is completed.

Here is a small example to create your own Node Middleware. It is very basic that adds the current date and time to the request object.

After the date and time are added, the request is moved to the next route. The code uses app.use() function to apply the middleware in the application and only the name of the middleware function is moved.

var express = require('express')

var app = express()

var requestTime = function (req, res, next) {

req.requestTime = Date.now()

next()

}

app.use(requestTime)

app.get('/', function (req, res) {

var responseText = 'Hello World!<br>'

responseText += '<small>Requested at: ' + req.requestTime + '</small>'

res.send(responseText)

})

app.listen(3000)

Another example would be setting up the middleware for routing simply bypassing the name of the middleware function. This coding can help you set up middleware as per the routes you specify.

var express = require('express')

var app = express(

var requestTime = function (req, res, next) {

req.requestTime = new Date().toLocaleString()

next()

}

app.get('/', requestTime, (req, res)=> {

var responseText = 'Hello World!<br>'

responseText += 'Requested at: ' + req.requestTime 

res.send(responseText)

})

app.get('/someother',(req,res)=>{

res.send("Hello World")

})

app.listen(3000)

What is Express Middleware?

Middleware can be defined as anything you insert in the middle of one layer of the software and another.

Express Middleware can be termed as functions that are compiled during the lifecycle of a request to the Express server. There is a battle going on between Express and Koa for good Middleware.

Every HTTP request and response is easily accessible by each middleware of each path it is attached to.

Moreover, the middleware can end the HTTP request independently or transfer it to another middleware function using the next () functionality. Since it happens in chaining, it allows you to categorize your code and generate reusable middleware.

Types of Express Middleware

There are five types of Express Middleware that may vary according to the level of application development.

Application-level middleware (app.use)

In application-level middleware, we can consider an authentication middleware and how it is created. For example, let us assume that there are five routes like getUsers, getDetails, updateDetails, isLoggedIn and isLoggedOut.

In this case, it is mandated that every route is authenticated. If the user is not authenticated, it is not possible to call the aforementioned routes.

When there is a need to build authentication for every GET, POST calls, there comes the development of an authentication middleware.

Auth-Middleware

As soon as you receive the authentication request, the authentication middleware makes progress on authentication code logic, available inside it.

If the authentication is successful, then the rest of the route must be called with the help of next () functionality. In case it fails, you may not be able to perform the next route exit and the middleware can throw some errors.

Router level middleware (router.use)

This is similar to the application level middleware and works in the same manner, except it can be generated and limited to an instance of express.Router ().

const router=express.Router ()

You can make use of the router.use () and router.METHOD () functions for loading router-level middleware.

const express = require('express');

const app = express();

const router = express.Router()

router.use((req,res,next)=>{

    console.log("Time:",new Date())

    next()

})

router.get("/user/:id",(req,res,next)=>{

    console.log('Request URL:', req.originalUrl)

    next()

},(req,res,next)=>{

    console.log('Request Type:', req.method)

    next()

},(req,res)=>{

    res.json({

        status:true,

        id:req.params.id

    })

})

app.use('/',router)

app.listen(3000,(req,res)=>{

    console.log('server running on 3000')

})

Built-in middleware (express.static, express.json, express.urlencoded)

This built-in middleware does not depend on the ‘Connect’ function and unlike the previous version of middleware, the version 4.X express now acts as a module.

In general, under the express types of middleware, you can utilize the below listed 3 built-in middleware functions.

  • static: This function act as a static asset to the application (HTML files, images and so)
  • json: This function computes the incoming request by joining hands with the JSON payloads. However, this built-in middleware not available with express version 4.16.0+

Express.urlencoded: This function computes the incoming requests by joining hands with the URL-encoded payloads. This built-in middleware also not available with the express version 4.16.0+

Error Handling Middleware (app.use (err, req, res, next))

Express.js is capable of handling any sort of errors when occurred because it has the tendency of default error handling and defined error-handling middleware functions, which is similar to the other middleware functions.

The only difference is along with error handling functions. Express middleware comes with four arguments instead of three.

app.use(function (err, req, res, next) {

 console.error(err.stack)

 res.status(500).send('Something broke!')

 })

Third-party middleware (bodyparser, cookieparser)

There are certain cases where you might need to add some additional features in the backend operations. In such cases, install the Node.js module for the specified functionality and then apply the same in your app either at the application level or router level.

Well, the above mentioned all middlewares will fill the ‘req.body’ property along with the parsed body during the ‘content-type’ request handler.

app.use({urlencoded:false})

const express = require('express');

const bodyParser = require('body-parser');

const app = express();

app.use(bodyParser.urlencoded({extended:false}))

app.use(bodyParser.json())

app.post('/save',(req,res)=>{

  res.json({

"status":true,

"payload":req.body

  })

}      

app.listen(3000,(req,res)=>{

 console.log('server running on port')

})

Requirements to Write Express Middleware

To generate, apply and test Express Middleware, you should have certain things installed prior. Firstly, install Node and NPM using the following syntax:

npm -v && node –v

Before you install, have a check whether you are installing the right versions of the Node and NPM versions.

In case it throws an error, you should install the Node again. Otherwise, you won’t be able to access the required Node JS Packages.

Preferably if you can install Node 10.9.0 and NPM 6.4.1, it should definitely work, or install Node of version 8 and higher and NPM versions 5 and more.

In order to test routes using any HTTP verbs except GET, install Postman in it.

Basic of Express Middleware

Using the very basics of Express that has middleware built-in for the very first time, you get an opportunity to know how middleware is used in application development, and how you can find a structured Express Middleware.

Use npm init     

Npm, install express – save; for creating a new project and npm inside it.

Create server.js and paste the code mentioned below.

const express = require('express');

const app = express();

app.get('/', (req, res, next) => {

  res.send('Welcome Home');

});

app.listen(3000);

Now run the server through Node server.JS and access http://localhost:3000. After this, you should be able to see the text Welcome Home appearing on your browser.

Take a look at an example of Express Request Logging Middleware in the following section:

Change the contents of server.js to:

const express = require('express');

const app = express();

app.use((req, res, next) => {

  console.log(req);

  next();

});

app.get('/', (req, res, next) => {

  res.send('Welcome Home');

});

app.listen(3000);

Now when you visit http://localhost: 3000, you should view the same information in your browser window.

At the same time, you can also see the output of the incoming request object in the console window. Now the middleware calls the next () function by logging out the HTTPS request object.

The next middleware in the pipeline manages to function with the get request to the root URL and at last, sends the text response back to the server. Using the app.use( ) function ensures that the middleware is called for every call to the application.

Take a look at an example for Restrict Express Request Content Type below.

Change the server.js file again to the below mentioned way:

const express = require('express');

const app = express();

const requireJsonContent = () => {

  return (req, res, next) => {

    if (req.headers['content-type'] !== 'application/json') {

        res.status(400).send('Server requires application/json')

    } else {

      next()

    }

  }

}

app.get('/', (req, res, next) => {

  res.send('Welcome Home');

});

app.post('/', requireJsonContent(), (req, res, next) => {

  res.send('You sent JSON');

})

app.listen(3000);

In the aforementioned example, start the server by running node server.js. To do this, as we have mentioned previously, you should have Postman installed.

Now open Postman and generate a post request to http://localhost:3000, and without setting any headers, run the request. By doing so, you will be able to see the message “Server requires application/JSON.”

Now get back to the previous screen and add the Content-type header by considering values of application/JSON. Now run the applied request and wait for the server to display the message “You sent JSON” on the screen.

Anytime, when you use Express Middleware make sure that you follow the order appropriately. Whenever a request is received by Express, each middleware matches the request is executed in the order it is initiated as long a terminating action occurs.

First, you receive an incoming request and then call the immediate middleware in the pipeline and when the action fails, the chain moves to the next middleware and finally, receives the response request.

Therefore, if an error occurs, the middleware handles it in order until any one of them stops calling the next () function.

Error Handling in Express Middleware

Express.JS naturally has the tendency of handling errors and comes with an in-built error handler. It is inserted always at the end of the middleware pipeline that can handle any unresolvable errors, which may have occurred in the pipeline.

It works by adding an error parameter to the standard parameters of the request, response and next, in an order.

The basic signature of Express Middleware appears as:

app.use((err, req, res, next) => {

  // middleware functionality here

})

If you want to call an error-handling middleware, you can simply pass on the error by calling the next () in the following format:

app.get('/my-other-thing', (req, res, next) => {

  next(new Error('I am passing you an error!'));

});

app.use((err, req, res, next) => {

  console.log(err);    

  if(!res.headersSent){

    res.status(500).send(err.message);

  }

});

In this code, the error handling middleware present at the end of the pipeline handles the error. The res.headersSent function efficiently checks whether the response has already sent the headers to the client. If it fails to send the headers, it updates a 500 HTTP status and the error message to the client.

You can even handle multiple types of error handling by chaining the error handling middleware.

Here is the best example to state how Express Middleware can handle multiple errors at a time.

app.get('/nonexistant', (req, res, next) => {

  let err = new Error('I couldn't find it.');

  err.httpStatusCode = 404;

  next(err);

});

app.get('/problematic', (req, res, next) => {

  let err = new Error('I'm sorry, you can't do that, Dave.');

  err.httpStatusCode = 304;

  next(err);

});

// handles not found errors

app.use((err, req, res, next) => {

  if (err.httpStatusCode === 404) {

    res.status(400).render('NotFound');

  }

  next(err);

});

// handles unauthorized errors

app.use((err, req, res, next) => {

  if(err.httpStatusCode === 304){

    res.status(304).render('Unauthorized');

  }

  next(err);

})

// catch all

app.use((err, req, res, next) => {

  console.log(err);

  if (!res.headersSent) {

    res.status(err.httpStatusCode || 500).render('UnknownError');

  }

});

In the above example, the middleware looks for a 404 error throw, if any. To clear the error, it renders the NotFound template page and later moves the error to the next item in the middleware.

The next middleware checks and validates whether there is a 304 error which is an unauthorized error.

In case the 304 error was found, the middleware renders the unauthorized page and passes the error again to the next middleware present in the pipeline.

In the end, the catch-all error handler records the types of errors encountered, and in case no response is sent, it transfers the error’s HTTP status code or an HTTP 500 status and finally, renders the template that contains UnknownError.

Read also: Why Node.js For IoT Is A Picture Perfect Story?

Creating Your Own Express.JS Middleware

Getting Started

Before you begin with the creation of Middleware in Node.js, it is important that you install Node.js first. Along with, set up an Express.JS application for successful creation. Creating your own Node.js Middleware process involves four simple steps.

Anatomy of Express Middleware

Express.JS Middleware has the following signature function

myCustomMiddleware(req, res, next) {

  // custom middleware here...

}

Req is an Express.JS request object, the Res is an Express.JS response object. The Next function commands your Express.JS to proceed to the subsequent middleware function that you have configured for your application.

The ideal purpose of Middleware is to modify the req or res objects, compile and execute any code you require, terminate the request-response session, and call the next middleware available in the stack.

Modifying the req Object

This is highly helpful in cases where you wish to analyze, understand and look for the currently logged in user on each request. For such instances, you can write a middleware as follows:

// getUserFromToken would be based on your authentication strategy

const getUserFromToken = require("../getUserFromToken");

module.exports = function setCurrentUser(req, res, next) {

  // grab authentication token from req header

  const token = req.header("authorization");

  // look up the user based on the token

  const user = getUserFromToken(token).then(user => {

    // append the user object the the request object

    req.user = user;

    // call next middleware in the stack

    next();

  });

};

Once you complete writing the code, it is important that you add it to your application. It is very simple to execute and by doing so, it enables the middleware for all routes present in your application. To enable the middleware, here is the code you require:

const express = require('express');

const setCurrentUser = require('./middleware/setCurrentUser.js');

const app = express();

app.use(setCurrentUser);

// ...

Modifying the res Object

With res, it is now easy to set a custom header on your response object, and it is quite simple with a middleware code such as the following:

module.exports = function addGatorHeader(req, res, next) {

  res.setHeader("X-Gator-Policy", "chomp-chomp");

  next();

};

Ending the Request/Response Cycle

The common functionality of middleware is to validate whether the user object has been perfectly fixed on your req object.

At the end of execution if you did not get the desired result or you cannot find the user, then terminating the request/response cycle is an ideal thing. To validate this approach, here is an example for your reference:

module.exports = function isLoggedIn(req, res, next) {

  if (req.user) {

    // user is authenticated

    next();

  } else {

    // return unauthorized

    res.send(401, "Unauthorized");

  }

};

The next step would be adding this middleware effectively to your application, where ordering becomes more crucial. Here is an example that supports the previous approach. Applying a new middleware to the existing user setting and additionally, creating authentication when using a single route.

The server.js coding is as follows:

const express = require("express");

const setCurrentUser = require("./middleware/setCurrentUser.js");

const isLoggedIn = require("./middleware/isLoggedIn.js");

const app = express();

app.use(setCurrentUser);

app.get("/users", isLoggedIn, function(req, res) {

  // get users...

});

In this case, only the /users path will expect the user to be authenticated.

Frequently Asked Questions
  1. What Is Node JS Middleware?

    Node JS Middleware functions are the functions that have access to the request-response object and the next function.

  2. How Do I Use Middleware In Node JS?

    There are some steps that you need to follow in order to use middleware in Node JS. They are as follows:

    • Execute any code
    • Make changes to the request and the response objects
    • End the request-response cycle
    • Call the next middleware in the stack
  3. What Is Express Middleware?

    Express is a routing and middleware framework that has minimal functionality. An Express app is basically a series of the middleware function call.

  4. What Is Express Router?

    Express router is a class that helps us to create route handlers. It can extend this routing to handle validation, 404 errors, etc.

  5. Is Express A REST API?

    The simple answer to this question would be NO. Express is not a REST API but can be the perfect choice for creating and executing REST APIs.

  6. What Are The Examples Of Middleware?

    Database middleware, application server middleware, message-oriented middleware, web middleware, and transaction-processing monitors.

  7. Is Express Hard To Learn?

    The simple answer to this question would be NO. Express.js is very easy to learn, use, and understand, even for a newbie.