This Express Middleware Tutorial explains all that a developer must know about middleware with respect to Express.js. It covers all major concepts related to a middleware along with practical examples and explains different middleware types in detail. Undoubtedly, Express.js plays a key role for a MEAN Stack Application as a middleware, so finally explaining how to develop our own custom middleware in Express.js?
Let’s dive deeper starting with an understanding of what a middleware is in general.
What is Middleware?
Express app is usually a web framework that consists of middleware and router. Therefore, an express application works through a series of middleware functions.
Middleware is:
- One or a series of callback functions that sits on top of the actual request handler and has the exact same parameter as actual request.
- A series of functions are invoked by the router layer of express app before the final request handler.
- A series of functions are invoked in order. This means the order in which they are written/included in a server.js file, are the order in which they are executed, given that the route matches.
- A function that receives the request and response objects of an HTTP request/response cycle.
- A function that can modify the request or response object before sending them to next middleware function in the series.
- It may update the response object or discontinue the chain if necessary.
- A function with a signature of (
req, res, next
), for example:
function logger(req,res,next){
console.log(new Date(), req.method, req.url);
next();
}
Here in this example, the next()
continues the chain of the series of functions known as middleware. next
is the third parameter in the middleware function and needs to be explicitly called at the end of the operation executed inside the function as, express has no way to understand when the function has come to the end of execution of current operation and the next method in the series needs to be invoked, therefore, next()
method needs to be called.
The following image can explain a middleware code:
What Middleware Does?
Middleware functions can be used in order to perform the following tasks:
- Execute any operation coded in the method.
- Update the request and the response objects.
- End the request-response cycle. For example, if there is any exception that is thrown, instead of calling the next method in the series of middleware, it can end the chain.
- As middleware in express is usually a series of methods / functions, Middleware is responsible to call the next middleware function in the series.
- The flow of middleware could be as follows:
Types of Middleware?
- Application-level middleware
- Router-level middleware
- Error-handling middleware
- Built-in middleware
- Third-party middleware
Application-level Middleware
This kind of middleware method is bind to the app Object
using app.use()
method. For example:
app.use(function (req, res, next) {
console.log('Current Time:', Date.now())
next()
})
In this example, a middleware function that prints the current time, has been mounted with app Object
using app.use()
method. However, this middleware function has neither mount path nor mount point. It is just executing a single instruction and not connecting to router.
However, in the second example,the middleware has a mount path ‘/book/:id
’. Therefore app.use()
accepts an optional path parameter just like the app.get()
and other routes as follows:
app.use('/book/:id', function (req, res, next) {
console.log('Request Type:', req.method)
next()
}
Now in the third example, application-level middleware has both mount-path and mount-point and instead of a single method, this example shows a series of middleware functions that are invoked one after another.
app.use('/book/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl);
next()
}, function (req, res, next) {
console.log('Request Type:', req.method);
next()
},
function (req, res, next) {
res.send();
})
Another way to use application-level middleware is to call app.METHOD()
. However, the only difference between app.use
and app.get
is that /books
to an app.get()
, would only be invoked when someone visited exactly /books
route, however, when /books
is a parameter to app.use()
, any request that starts with /books
will invoke the app.use
function. For example:
app.get('/book/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl);
next()
}, function (req, res, next) {
console.log('Request Type:', req.method);
next()
},
function (req, res, next) {
res.send();
}
Router-level Middleware
Router-level middleware can be used by using router.use()
or router.METHOD()
.
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Hello World!' });
});
OR:
router.use('/book/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
console.log('Request Type:', req.method)
next()
}
Error-handling Middleware
Unlike application-level and router-level, error-handling middleware takes four arguments, for example:
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
})
Built-in Middleware
Starting with version 4.x, there is only one built-in middleware which is express.static
.
app.use(express.static(path.join(__dirname, 'public')));
This middleware function is based on serve-static
, and is responsible for loading static assets such as HTML files, images, and so on.The function signature is:
express.static(root, [options])
Here, root
is the directory name and options are several options. The following table describes the properties of the options
object, see express.static.
Property | Description | Type | Default |
dotfiles | Determines how the files or directories that begin with a dot "." are treated. | String | ignore |
etag | Enable or disable etag generation. | Boolean | true |
extensions | If a file is not found, search for files with the given extensions and load the first one found. Example: [‘html’, ‘htm’]. | Boolean | false |
fallthrough | Let client errors fall-through as unhandled requests, otherwise forward a client error. | Boolean | true |
index | Sends the specified directory index file. Set to false to disable directory indexing. | Mixed | index.html |
lastModified | Set the Last-Modified header to the last modified date of the file on the OS. | Boolean | true |
maxAge | Set the max-age property of the Cache-Control header in milliseconds or a string in ms format. | Number | 0 |
redirect | Redirect to trailing "/ " when the pathname is a directory. | Boolean | true |
setHeaders | Function for setting HTTP headers to serve with the file. | Function | |
Third-party Middleware
There are a number of third party middleware, such as body-parser.mongoose
, morgan
and so on. These can be installed by using command:
npm install <module name>
And they can be loaded using requires and used later. For example:
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))
How to Create a Middleware?
To create a middleware that will print the current time and save a book to database and render a message, follow the steps given below:
- First, create the method for logging current time.
var requestTime = function (req, res, next) {
req.requestTime = Date.now();
console.log("Current Time for Request"+req.requestTime );
next()
};
- Use the middleware function as an application-level middleware.
app.use(requestTime);
- Create a middleware to connect to DB.
var conencttodb = function(req, res, next){
try
{
var path= 'mongodb://localhost:27017/library';
connect = mongoose.connect(path);
console.log('conencted to db!!');
}
catch(e)
{
console.log(e);
}
};
app.use(conencttodb)
- Save a book as the next in middleware.
var book1 = new Book({
title: 'Peter Quill',
author: 'starlord55',
yearpubished: 2011,
id: 101,
pages:56,
ratings:1
});
book.save(function(err,req, res) {console.log(req.body);
if(err) {
console.log(err);
res.send({
message :'something went wrong'
});
} else {
res.send({
message:'the book has bees saved at'+req.requestTime
});
}
});
Every method will be executed one after another in order.
More MEAN Stack and Related Tutorials
The post All you need to Know about Express Middleware appeared first on Web Development Tutorial.