fbpx

Introduction

Middleware is a function that executes the lifecycle method to an Express server, and utilizes the request and response cycles. Express.js offers built-in middleware, and allows you to produce custom versions for precise functionality such as preventing a user from performing a certain operation or logging the path for an incoming request to your application.

In this article, you will learn about how to create a custom middleware in Express.js today.

Analyzing an Express Middleware

All middleware functions in Express.js accept three arguments following the requestresponse, and next lifecycle methods. In your index.js file, define a function with the three lifecycle methods as arguments:

function myCustomMiddleware(req, res, next) {
// …
}

The first argument, req, is shorthand for the request object with built-in properties to access data from the client side and facilitate HTTP requests. The res argument is the response object with built-in methods to send data to the client side through HTTP requests. The argument, next, is a function that tells Express.js to continue on to the following middleware you have configured for your application.

Middleware has the ability to modify the req and res objects, run any code you wish, end the request and response cycle, and move onto the following functions.

Note the order of your middleware, as invoking the next() function is required in each preceding middleware.

Now that you’ve reviewed the three arguments that build a middleware, let’s look at how to assemble a custom middleware.

Using the req Object

To identify the currently logged in user, you can construct a custom middleware that can fetch the user through authentication steps. In your setCurrentUser.js file, define a function that accepts the three lifecycle methods as arguments:

// Require in logic from your authentication controller
const getUserFromToken = require("../getUserFromToken");

module.exports = function setCurrentUser(req, res, next) {
  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();
  });
};

Within your setCurrentUser() function, the req object applies the built-in .header() method to return the access token from a user. Using the authentication controller method, getUserFromToken(), your req.header() logic passes in as an argument to look up the user based on their token. You can also use the req object to define a custom property, .user to store the user’s information. Once your middleware is complete, export the file.

You can enable your custom middleware in your Express server by applying the built-in Express.js middleware, .use().

In your server.js file, instantiate an instance of Express and require in your setCurrentUser() custom middleware:

const express = require('express');

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

const app = express();

app.use(setCurrentUser);

// ...

The app.use() middleware accepts your custom middleware as an argument, and authorizes your logic in your Express server.

Applying the res Object

You can also create a custom middleware to handle functionality on your response object, such as designing a new header.

In your addNewHeader.js file, define a function and utilize the .setHeader() method on the res object:

module.exports = function addNewHeader(req, res, next) {
  res.setHeader("X-New-Policy", "Success");
  next();
};

Here, the .setHeader() method will apply the new header, Success, on each function call. The next() method will tell Express.js to move on to following middleware once the execution completes.

Ending the Request and Response Cycle

Express.js also allows you to end the request and response cycle in your custom middleware. A common use case for a custom middleware is to validate a user’s data set on your req object.

In your isLoggedIn.js file, define a function and set a conditional to check if a user’s data exists on the req object:

module.exports = function isLoggedIn(req, res, next) {
  if (req.user) {
    next();
  } else {
    // return unauthorized
    res.send(401, "Unauthorized");
  }
};

If the user’s data exists in the req object, your custom middleware will move on to following functions. If a particular user’s data is not in the object, the .send() method on the res object will forward the error status code 401 and a message to the client side.

Once you’ve set your middleware, export the file and navigate to your Express.js server. In your server.js file, require in and insert your custom middleware as an argument in a GET request to authenticate a user through a single route:

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) {
  // ...
});

The route /users handles the logic within your isLoggedIn custom middleware. Based on the order of your Express server, the route can also access the setCurrentUser middleware as it is defined before your GET request.