Mastering Middleware in Express.js: A Beginner's Guide

Mastering Middleware in Express.js: A Beginner's Guide

Everything you need to know about using middleware in your Express.js routes, including types, best practices, and custom middleware examples.

Β·

6 min read

Introduction

Hey there! Welcome to a new blog post about middleware in Express.js!

If you're new to Express.js, you might not be familiar with the concept of middleware, but it is an important aspect of the framework that is worth understanding.

In this blog post, we'll be covering everything you need to know about middleware in Express.js, including what it is, how it works, and how to use it in your routes. So, let's get started!

What is middleware? πŸ€”

Middleware in Express.js is a function that is executed between the incoming request and the outgoing response.

It can be used to modify the request and response objects, perform tasks such as authentication and validation, and even terminate the request-response cycle.

How does it work? βš™οΈ

Middleware is defined using the app.use() function, which takes a function as an argument. The function can have three arguments: the request object, the response object, and the next function in the middleware chain.

Example

app.use((req, res, next) => {
  console.log('A request was made!');
  next();
});

This middleware function will be executed for every incoming request, and it will log a message to the console.

The next() function is used to move to the next middleware function in the chain, or to the final route handler if there are no more middleware functions.

Types of middlewares

There are several different types of middleware available in Express.js, each with its own specific use case.

Here are a few examples:

Application-level middleware

This type of middleware is executed for every incoming request, regardless of the route. It can be used to perform tasks such as logging, parsing request bodies, and setting response headers.

Router-level middleware

This type of middleware is specific to a particular router and is executed only for requests that match the router's path. It can be used to perform tasks such as authorization, validation, and error handling.

Error-handling middleware

This type of middleware is used to handle errors that occur in the application. It takes four arguments: the error object, the request object, the response object, and the next function.

Third-party middleware

There are many third-party middleware libraries available for Express.js, such as body-parser, cors, and helmet. These libraries provide additional functionality that can be easily integrated into your application.

Using middleware in code πŸ’»

Routing example

Middleware can be used in Express.js routes to perform tasks such as authentication, validation, and error handling.

For example, consider the following route that requires authentication:

app.get('/secret', authenticate, (req, res) => {
  res.send('You have access to the secret page!');
});

function authenticate(req, res, next) {
  if (req.headers.authorization !== 'secret') {
    return res.status(401).send('Unauthorized');
  }
  next();
}

In this code, authenticate function is a middleware function that checks the authorization header of the request.

  1. If the header is not set to secret, the middleware function returns a 401 status code and a message saying "Unauthorized".

  2. If the header is set to secret, the middleware function calls the next() function, which moves on to the final route handler.

Chained middleware example

Middleware functions can also be chained together, allowing you to perform multiple tasks in a single route.

For example:

app.get('/secret', validate, authenticate, (req, res) => {
  res.send('You have access to the secret page!');
});

function validate(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(400).send('Missing authorization header');
  }
  next();
}

function authenticate(req, res, next) {
  if (req.headers.authorization !== 'secret') {
    return res.status(401).send('Unauthorized');
  }
  next();
}

In this example, the validate function is executed before the authenticate function.

  1. If the authorization header is missing, the validate function returns a 400 status code and a message saying "Missing authorization header".

  2. If the header is present, the validate function calls the next() function, which moves on to the authenticate function.

Just another example

app.use((req, res, next) => {
  console.log('I see you making that request...');
  setTimeout(next, 1000);
});

app.get('/', (req, res) => {
  res.send('I see you made it here...');
});

This middleware function logs a message to the console and waits for one second before calling the next() function.

The resulting delay might be frustrating for users, but it can be a useful technique for simulating slow network conditions during testing. Just don't use it in production! πŸ˜‰

Custom middleware example

It's easy to write your own custom middleware in Express.js. All you need to do is define a function and pass it to the app.use() function. For example:

function logger(req, res, next) {
  console.log(`${req.method} request made to ${req.originalUrl}`);
  next();
}

app.use(logger);

This middleware function will log a message to the console every time a request is made to the server. You can also specify a path for the middleware function to only be executed for requests matching that path. For example:

app.use('/api', logger);

This middleware function will only be executed for requests made to the /api path.

Best practices for using middleware βœ…

Here are a few best practices for using middleware in Express.js:

  • Keep middleware functions small and focused on a single task. This will make them easier to understand and reuse.

  • Use the next() function to move to the next middleware function or route handler. If you forget to call next(), the request-response cycle will be terminated and the client will not receive a response.

  • Don't modify the request and response objects in place. Instead, create new objects and assign them to the request and response objects.

    This will prevent unintended side effects and make your code easier to understand.

  • Use router-level middleware for tasks that are specific to a particular route, and use application-level middleware for tasks that are global to the application.

  • Consider using third-party middleware libraries to save time and avoid reinventing the wheel.

Conclusion ✍🏻

In this blog post, we've covered the basics of middleware in Express.js, including what it is, how it works, and how to use it in your routes.

We've also looked at different types of middleware and best practices for using middleware in your application.

Resources πŸ“‘

If you want to learn more about middleware in Express.js, there are many great resources available online.

Some good places to start include:

Thank you for reading! πŸŽ‰

That's it for our blog post on middleware in Express.js. Thank you for reading this article!

If you enjoyed this article, be sure to subscribe to my newsletter to stay up-to-date with my content.

And if you need any help or have any questions, don't hesitate to reach out – I'm happy to help out. See you on Twitter! πŸ‘‹πŸ»

Did you find this article valuable?

Support Nikhil's Blog by becoming a sponsor. Any amount is appreciated!