A Simple Explanation Of Express Middleware

Published Dec 06, 2017Last updated Dec 13, 2017

Basic Idea:

A web server can be seen as a function that takes in a request and outputs a response. Middlewares are functions executed in the middle after the incoming request then produces an output which could be the final output passed or could be used by the next middleware until the cycle is completed, meaning we can have more than one middleware and they will execute in the order they are declared. middleware A below will execute before middleware B, middleware Bbefore middleware C.We can pass variable from one middleware to another.


Middleware Usage:

To set up a middleware, you can invoke app.use() for every middleware layer that you want to add. Middleware can be generic to all paths, or triggered only on specific path(s) your server handles. Below is an example of middleware declaration.

var app = express();
app.use(function () {}) //added to all paths or globally
app.get('/someroute', function() {}) //added to a specific path

A Closer Look At Middleware:

When you use app.use('/some_route', myCallBack()). Express will listen for requests for that route, and when it’s hit, it will call the function you provided and give it three parameters: request, response and next (actually four but let keep things simple for now).

Your callback might be defined like this:

function myCallback(a, b, c) {} //sample 1

or like this:

function myCallback(req, res, next) {} //sample 2

or simply

function myCallback(){} //sample 3

In sample 1 above, you can access the request by using a the parameter. In your sample 2, you’ll access it by using the reqparameter. In the third case, you can use arguments[0]. The params are the request , response and next. No matter what you call them or not, express will in its internal workings call the function you provided like this:

function myCallback(requestObject, responseObject, nextMiddleware) {}

TherequestObject: contains information about the HTTP request. You can access the request headers, full url, caller IP address etc within the requestObject.

The responseObject: is use to handle the requestObject. The responseObject represents the HTTP response that an Express app sends when it gets an HTTP request.

The next : this may accept a parameter or may not. When it does not accept a parameter, it means go to the next executable. It is a way to escape from the middleware function. When you pass parameter to the next function i.e next(parameter), you are telling express that an error occur in the middleware. There are times when you need do this, we are going there soon.

Cool Use Cases Of Middleware:

There are a number of middlewares online that we can use in our application to modify request i.e app.use(express.bodyParser()), app.use(express.cookieParser()) but we also can use custom middleware within our application which examples include:

Routing: middleware can be use to define different routes within our express application

app.get('home', function (req, res) { 
  res.render('home'); //when i visit home url, render the home view
});

app.post('another-route', function (req, res) { 
  res.sendStatus(200);
});

Error Handling: There is a middleware in express denoted as the Error Middleware. This middleware takes four (4) parameters like below:

function (error, req, res, next) {}

Express will scan through all our functions, if it finds a middleware with four (4) params and not two or three. It denote the middleware as an error middleware meaning it will give you access to any error thrown by any of the middleware before it, remember I said earlier that when you pass parameter into the next(err) function within our middleware, it denotes that an error occurred within that middleware. It is this error middleware that will be able to access any error thrown from any of the middlewares before it.

app.get('home', function (req, res) { 
  res.render('home');
});

app.post('another-route', function (req, res, next) { 
  try {
    	//something 
    } catch (err) { 
    	next(err); 
    }
});

//below is use to handle general error within our application
app.use(function (error, req, res, next) { 
  res.locals.error=err; //get error thrown from another-route above 	   	           res.render("error-page");
});

Guard specific routes: we can use middleware to guard specific routes within our application. Take for example, I have a dashboard page and I only want users with a session(already logged in) be able to visit that page, I can use middleware to block it like below:

//guard
let requiresLogin = function(req, res, next) { 
  if (! req.session.loggedIn) { 
    	err = new Error("Not authorized"); 
        next(err); 
     } 
     return next();
};

//protected route
app.get('dashboard', requiresLogin, function (req, res) { 
  res.render('home');
});

//general error handler
app.use(function (error, req, res, next) { 
  res.locals.error = err; //get error thrown from another-route abovres.render("error-page");
});

I am happy to share with you what I know about express middleware. If you’ve enjoyed this article, do show support by giving a few claps 👏_ . Thanks for your time and make sure to follow me or drop your comment below_ 👇

Discover and read more posts from Abel AGOI
get started