Click here to Skip to main content
15,890,670 members
Articles / All Topics

All You Need to Know About Express Middleware

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
23 Feb 2017CPOL5 min read 12.2K   4  
Everything you need to know about Express Middleware

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:
    JavaScript
    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 is Middleware

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

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:

JavaScript
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:

JavaScript
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.

JavaScript
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:

JavaScript
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().

JavaScript
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Hello World!' });
});

OR:

JavaScript
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:

JavaScript
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  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.

JavaScript
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:

JavaScript
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.

PropertyDescriptionTypeDefault
dotfilesDetermines how the files or directories that begin with a dot "." are treated.Stringignore
etagEnable or disable etag generation.Booleantrue
extensionsIf a file is not found, search for files with the given extensions and load the first one found. Example: [‘html’, ‘htm’].Booleanfalse
fallthroughLet client errors fall-through as unhandled requests, otherwise forward a client error.Booleantrue
indexSends the specified directory index file. Set to false to disable directory indexing.Mixedindex.html
lastModifiedSet the Last-Modified header to the last modified date of the file on the OS.Booleantrue
maxAgeSet the max-age property of the Cache-Control header in milliseconds or a string in ms format.Number0
redirectRedirect to trailing "/" when the pathname is a directory.Booleantrue
setHeadersFunction 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:

JavaScript
npm install <module name>

And they can be loaded using requires and used later. For example:

JavaScript
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.
    JavaScript
    //create a method to
    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.
    JavaScript
    //use the middleware as an application-level middleware
    app.use(requestTime);
  • Create a middleware to connect to DB.
    JavaScript
    // method to conenct to be
    
    var conencttodb = function(req, res, next){
      try
      {
        var path= 'mongodb://localhost:27017/library';
        connect = mongoose.connect(path);
        console.log('conencted to db!!');
        //mongoose.set('debug', true);
      }
      catch(e)
      {
        console.log(e);
      }
    };
    app.use(conencttodb)
  • Save a book as the next in middleware.
    JavaScript
    // create a new book
    var book1 = new Book({
      title: 'Peter Quill',
      author: 'starlord55',
      yearpubished: 2011,
      id: 101,
      pages:56,
      ratings:1
    });
    
    // save the book in database
    book.save(function(err,req, res) {console.log(req.body);
    
      if(err) {
        console.log(err);
        res.send({
          message :'something went wrong'
        });
      } else {
       // res.contentType('application/json');
        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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Emaratech
United Arab Emirates United Arab Emirates
Imran Abdul Ghani has more than 10 years of experience in designing/developing enterprise level applications. He is Microsoft Certified Solution Developer for .NET(MCSD.NET) since 2005. You can reach his blogging at WCF Tutorials, Web Development, SharePoint for Dummies.

Comments and Discussions

 
-- There are no messages in this forum --