Writing Express Middleware
Tags: webdev, node, programming, javascript
Published: 2021-01-24 22:01:39

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

Middleware functions are functions that have access to the request and response objects, and the next function for call the next middleware.

In this article, we’ll look at what Express middleware does and how we can write them.

Characteristics of Middleware
=============================

Middleware functions can run any code, make changes to the request and response object, end the request-response cycle, and call the next middleware in the stack.

A middleware may look something like the following code:

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

The code above has the request method in which the middleware will be called, which is the `get` in `app.get` .

Then we have the `'/'` which is the route path.

Finally, the middleware function that we pass in has the request and response objects as the first 2 parameters respectively, and the `next` function, which we call to run the next middleware.

Example
=======

For example, we can write a middleware to log some output when we make a request to the `/` route.

We can write this as follows:

```
const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.get('/', (req, res, next) => {  
  console.log('middleware called');  
  next();  
});

app.get('/', (req, res) => {  
  res.send();  
})

app.listen(3000, () => console.log('server started'));
```

`next` will call our route handler for the `/` route.

We should get `middleware called` from the `console.log` output and an empty response.

To load the middleware for all routes, we can use `app.use` instead of `app.METHOD` where `METHOD` is the request method is in lower case.

For example, we can write an app-wide middleware as follows:

```
const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.use((req, res, next) => {  
  console.log('middleware called');  
  next();  
});

app.get('/', (req, res) => {  
  res.send();  
})

app.listen(3000, () => console.log('server started'));
```

We should get the same thing as before, but if we have:

```
const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.use((req, res, next) => {  
  console.log('middleware called');  
  next();  
});

app.get('/', (req, res) => {  
  res.send();  
})

app.post('/foo', (req, res) => {  
  res.send('foo');  
})

app.listen(3000, () => console.log('server started'));
```

We get `middleware called` when we make a GET request to `/` and a POST request to `/foo` .

Modifying the Request and Response Objects
==========================================

We can attach new properties and set values for the request and response objects.

For example, we can write:

```
const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.use((req, res, next) => {  
  req.requestTime = Date.now();  
  next();  
});

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

app.post('/foo', (req, res) => {  
  res.json(req.requestTime);  
})

app.listen(3000, () => console.log('server started'));
```

Then we get the timestamp of when the request is made when we make a GET request to `/` and a POST request to `/foo` .

Likewise, we can do something similar with the response object:

```
const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

app.use((req, res, next) => {  
  res.responseTime = Date.now();  
  next();  
});

app.get('/', (req, res) => {  
  res.json(res.responseTime);  
})

app.post('/foo', (req, res) => {  
  res.json(res.responseTime);  
})

app.listen(3000, () => console.log('server started'));
```

We also will get the timestamp of when the response is made when we make a GET request to `/` and a POST request to `/foo` .

Configurable Middleware
=======================

We can make a function that has optional parameters and return a middleware function to create a configurable middleware function.

For example, we can write one as follows:

```
const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))

const configurableMiddleware = (options) => {  
  return (req, res, next) => {  
    req.options = options;  
    next();  
  }  
}

app.use(configurableMiddleware({ date: new Date(), foo: 'bar' }));

app.get('/', (req, res) => {  
  res.json(req.options);  
})

app.listen(3000, () => console.log('server started'));
```

The `configurableMiddleware` function takes an options object as a parameter and then return a middleware function with the `req.options` property set to the `options` parameter.

Then when we make a request to the `/` route then we get:

```
{"date":"2019-12-23T22:37:04.927Z","foo":"bar"}
```

as the response.

Conclusion
==========

We can use Express middleware functions to run code before a route handler or another middleware is run.

To create a middleware function, we just have to create a function with the request and response objects as the first 2 parameters and the next function as the third parameter.

We can modify the request and response objects by adding new properties to it and set a value for them.

Then we call `next` to call the next middleware or route handler.

We can create configurable middleware by creating a function that takes an options parameter and returns a middleware function.