Express.js Middleware in Javascript

What is middleware?

Middleware allows you to interact with the request and response object in your code. As the name suggests, it comes in the middle to provide services to applications. In the middle of what though? Well, I’ll let this illustration explain that to you.

Middlewares are capable of changing requests, response objects, and can end the response cycle as well. For simplicity, you can think of middleware as a group of functions that will execute whenever a request to the server has been made.

Why use middleware?

On most websites, any time you interact with the browser, it requests information from a web server. The web server then sends a response back to the browser which it then converts and shows it to you as text, image, video, etc.

When the web-server receives a request, Express (a web-application server framework for node.js) gives you a request object where you can see the data they are requesting along with some user details such as IP address, browser language, passed parameters, etc. Express also gives you access to a response object. These objects are usually shortened to req, res.

Let’s take an example. Assume a user visited your website and logged in with some credentials. Now a request object has been sent to your web server. You need to authenticate the user and also log into the database that <user> signed in at the given <time> with the <used device> and <IP> before sending the response object back to the browser. Moreover, you also need to check the database to find the page of your website that the user browsed the last time he/she used it and modify the request object to let him/her continue from there. How do you do that? You use middleware functions!

Middleware functions are the perfect place to modify the req and res objects. For instance, here, once the user has signed in, you can authenticate the user from the database and then update his details in res.user.

Middleware gives you access to req and res objects in the app’s request-> response cycle.

Middleware functions can perform the following tasks:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware in the stack using next()

What is next()?

As mentioned earlier middleware can be assumed as a group of functions whenever a request has been made to the server. Well, since it is a group of functions, how is the order in which they execute be decided? and how will the execution flow be maintained? Firstly, the order of execution is decided by the order of loading of functions. For a basic code, we will just load the functions in app.get(). Here is a simple example →

app.get('/', authenticate, log_data, update_req);

Now the ordering of middleware functions is decided → authenticate(), log_data() and then update_req().

But how will the flow of execution go from one middleware function to another? Well, this is when the next() function comes into the picture.

A middleware function typically receives three arguments: req, res and next . next is the next function which will be executed after the current one.

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

For example, in the above case, our function orders are authenticate(), then log_data() and then update_req() The code for the middleware will then look something like this →

const authenticate = function (req, res, next) {
    // code to authenticate user
    next();
}
const log_data = function(req, res, next) {
    // code to log signin data in database
    next();
}
const update_req = function(req, res, next) {
    // code to update req object
}

The next function can be named otherwise too but this is the convention followed to avoid any confusion.

Note: Using next() in the last function(update_req) is optional and won’t do anything since it is the last function in the request-response cycle.

We don’t always load the functions in the arguments of app.get(). We can also use app.use(), route.use(), etc.

Coding Middleware

You can code your middleware in several ways. You can also use third-party middleware functions if you want. First of all, you need to load your middleware function. There are two basic ways to do that →

  • Load it as parameters in app.get() as shown above
  • Load it using app.use() . This is a conventional and better way.

app.get() is called only when the HTTP method used in the request is GET whereas loading a function via app.use() means it will be called every time a request is made to the application(doesn’t matter what the HTTP method is). Therefore, app.use() is considered a better way to load the middleware.

Updating the code above using the 2nd technique, it will look something like this →

const authenticate = function (req, res, next) {
    // code to authenticate user
    next();
}
app.use(authenticate);
const log_data = function(req, res, next) {
    // code to log signin data in database
    next();
}
app.use(log_data);
const update_req = function(req, res, next) {
    // code to update req object
}
app.use(update_req);
app.get('/');

Here, the order of functions is decided in the order they are loaded, which is first authenticate, the log_data, and then update_req.If you use built-in or third-party middleware, just import the function and load it using app.use(). A commonly used built-in middleware is cookie-parser. It is used to parse cookie header and populate req.cookies. You can include this in your code very easily →

const cookie_parser = require('cookie-parser');
app.use(cookie_parser());

You can find some commonly used built-in express middleware functions here.

Conclusion

Middleware is a great tool to organize your code to work in the request-response cycle. It is basically a function that has access to the req and res objects of your application. It can be thought of as a series of tasks that the developer performs before the request is handled by the application. You can code your own middleware functions or use built-in or 3rd party functions.

Please comment with your feedback below.

Happy Learning!