Adding layers of functionality to your Express application with functions.

Scroll down...




Look at how the Express documentation defines Middleware:

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle

Does any of that ring a bell? We've already dealt with functions that access the request and response objects. Our route handling functions dealt with the req and res. However, they could not access "the next middleware function in the application’s request-response cycle." So those handler functions weren't technically Middleware, but they were not very different either.

Middleware allows you build a pipeline of functions that can react to or transform the request and response. A simple example would be a piece of logging middleware. Say we want our application to function precisely as it had been, except we want to add a layer of logging that prints out each request URL and to the console—if you think layers, you should think Middleware.

Let's see we could add some logging to our wonderfully basic application.

Building Middleware

Connecting a simple middleware function doesn't look too much different than our earlier route handler functions. Here's how we can add a piece of middleware to our basic "Hello World" application.

  app.use(function (req, res, next) {
    console.log(req.url + " — " + new Date())

There are three differences between this and a route handler. Firstly, we are passing this function to use rather than one of the HTTP method functions like get (remember Express provides you with helper methods that map to HTTP verbs: get() for GET requests, post() for POST requests, etc.). Secondly, we are only passing in a function, there is no path string. You can pass a path string as the first argument, and if you do so, the middleware will only execute on requests to the given path. When no path string is supplied, such as in our example, the middleware will execute on every request. Finally, our middleware function has the next parameter. This is a function that lets Express continue on to the next piece of middleware. If you forget to pass in and call next, then your application will hang indefinitely; watch out for this! Always call next() at the end of the middleware method (next() tells Express to move on to next middleware or to the callback function associated with your endpoint).

Code Review

Here's our application with our new slice of middleware.

const express = require('express')
const app = express()

app.set('view engine', 'hbs')

app.use(function (req, res, next) {
  console.log(req.url + " — " + new Date())

app.get('/', function (req, res) {

app.get('/names/:name', function (req, res) {
  const name = req.params.name
  res.render('hello', {name})

app.listen(3001, function () {
  console.log('Odin is listening on port 3000!')

Wrapping Up

Middleware isn't much more than a pile of functions. It's not so intimidating once you realize there isn't any hidden magic. Because they are just JavaScript functions, your Middleware can be as small or as powerful as you want it to be. Express is all about building with small, composable pieces, and now most of those pieces are in your reach.

Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

There are no additional resources for this lesson just yet!

Sorry, comments aren't active just yet!

Next Lesson: Deploying with Heroku