Making your own Express Middleware
Tags: typescript, javascript, webdev, tutorial
Published: 2022-06-19 17:10:50

Express is a common way to display static routes to a user. It is even more commonly used to create APIs for Node.JS. In Express, it's easy to define a URL, and what will happen at that URL. We can also define **middleware**, which runs before the final request is returned. This can let us to alter the request, and do it in a standard way across many routes. 

If you've used Express, you may have already used pre-built middlewares like `bodyParser` or `jsonParser`. In this guide, let's look at how you can create your own custom middleware.

## Creating a middleware in Express 
A middleware is simply something which data passes through on its way to its actual end location. Consider you have a route like this:

```javascript
import express from 'express';
const app = express()

app.get('/home/', (req, res, next) => {
    if(req.getRoute == true) {
        res.status(200).send("Hello world!")
    }
    else {
        res.status(200).send("Goodbye world!")
    }
})
```

In this example, if the request or `req` has the property `getRoute` set to true, we will show a different set of text. By default, HTTP requests do not have a property called `getRoute`. Of course, it would be easy to set it within `/home/` itself, but imagine you had multiple requests, all depending on this one `getRoute` property:
```javascript
import express from 'express';
const app = express()

app.get('/home/', (req, res, next) => {
    if(req.getRoute == true) {
        res.status(200).send("Hello world!")
    }
    else {
        res.status(200).send("Goodbye world!")
    }
})

app.get('/home/article', (req, res, next) => {
    if(req.getRoute == false) {
        res.status(200).send("This is my article");
    }
    else {
        res.status(400).send("ERROR OCCURRED");
    }
})
```

Now we have a situation where a middleware might make sense. There are two ways to define a middleware - with `use()`, or via a function. Let's look at `use()` first.

## use() as a middleware

Considering our previous example, we can use `use()` to write a function that runs on **every** route. This is therefore a general middleware, which will run any time the user goes to any valid route on your server. Here is an example, where we define `getRoute` within a `use()` middleware:
```javascript
app.use((req, res, next) => {
    // Add getRoute to our request object
    req.getRoute = true;
    // Next tells express to now go to the next valid function.
    next();
});

app.get('/home/', (req, res, next) => {
    if(req.getRoute == true) {
        res.status(200).send("Hello world!")
    }
    else {
        res.status(200).send("Goodbye world!")
    }
})

app.get('/home/article', (req, res, next) => {
    if(req.getRoute == false) {
        res.status(200).send("This is my article");
    }
    else {
        res.status(400).send("ERROR OCCURRED");
    }
})
```

Using this middleware, we can add `getRoute` to our request, and it'll now be available to `/home/` and `/home/article`. It'll also be available to any other route on your server. When we call `next()`, it tells Express to go onto the next valid route. For example, if the user went to `/home/`, then first our middleware would be called, and then since we called `next()` within it, Express would go to the `/home/` route, as we have it defined.

## Use case: API Verification
A trick I often use for generalised middlewares is to split functionality that applies to certain HTTP methods. For example, if I wanted to apply an API verification function to all `POST` requests, I can easily do that in a standard middleware used by the entire app:
```javascript
import { apiVerification } from './util.js'
app.use(async (req, res, next) => {
    // Here, apiVerification is a function that returns true if the right request is sent.
    // We only want to apply it to POST methods, though, so lets add that to our middleware.
    if(req.method == "POST") {
        let verifyCredentials = await apiVerification(req);
        if(verifyCredentials) {
            next();
        }
        else {
            res.status(400).send("ERROR OCCURRED");
        }
    }
    else {
        // For everything else, like "GET", go to next valid route.
        next();
    }
});
```

This is a perfect way to add a standard verification method to all your `POST` routes, without having to redefine and recall `apiVerification` every time. If `apiVerification` fails, the user is given an error message instead. For other methods like `GET`, this `apiVerification` step is skipped is skipped.

## Specific Middlewares

Sometimes, you only want a middleware to apply to specific routes, rather than generally to everything. For that, we need to define them in a function. Using our previous example, we can create a function for `req.getRoute`, and apply it to only the routes we want to:
```javascript
let setGetRoute = (req, res, next) => {
    req.getRoute = true;
}

app.get('/home/', setGetRoute, (req, res, next) => {
    if(req.getRoute == true) {
        res.status(200).send("Hello world!")
    }
    else {
        res.status(200).send("Goodbye world!")
    }
})

app.get('/home/article', (req, res, next) => {
    if(req.getRoute == undefined) {
        res.status(200).send("This is my article");
    }
    else {
        res.status(400).send("ERROR OCCURRED");
    }
})
```

Now `req.getRoute` will only be available to `app.get('/home/'..`, since we only added that function to that route (`app.get('/home/', setGetRoute...`). For `/home/article`, `req.getRoute` will not be available.

This is quite useful when we only want to provide certain functionality in specific situations.

## Conclusion

Middlewares are a powerful part of Express, and let us process requests differently, or apply certain functions to all requests. I hope you've enjoyed this article. To [learn more about Javascript, click here](https://fjolt.com/category/javascript).