Making your own Express Middleware
📣 Sponsor
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:
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:
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:
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:
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:
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.
More Tips and Tricks for Javascript
- The Javascript API to Access a User's Local Files
- Web Components and the Shadow DOM
- How fetch works in Javascript
- Javascript Promise.all() - Everything you need to know
- How to Change CSS with Javascript
- Asynchronous Operations in Javascript
- Javascript Dates and How they Work
- Waiting for the DOM to be ready in Javascript
- Javascript Ordinals: Adding st, nd, rd and th suffixes to a number
- An Introduction to Javascript Objects