Using middleware

Express is a lightweight routing and middleware web framework. An Express application is essentially a series of middleware function calls executed during the request-response cycle.

Middleware functions are functions that have access to:

Middleware functions can perform the following tasks:

If a middleware function does not end the request-response cycle, it must call next(). Otherwise, the request will remain pending.

Express applications can use the following types of middleware:

You can load middleware functions with an optional mount path. Multiple middleware functions can also be grouped together to create a middleware sub-stack at a specific mount point.

Application-level middleware

Application-level middleware is bound to an instance of the app object using:

where METHOD is the lowercase HTTP method such as get, post, put, or delete.

Middleware without a mount path

The following middleware runs for every incoming request:

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

app.use((req, res, next) => {
  console.log('Time:', Date.now())
  next()
})

Middleware mounted on a specific path

The following middleware runs for all request types on /user/:id:

app.use('/user/:id', (req, res, next) => {
  console.log('Request Type:', req.method)
  next()
})

Route handler example

This route handles GET requests to /user/:id:

app.get('/user/:id', (req, res) => {
  res.send('USER')
})

Multiple middleware functions

Middleware functions can be chained together to form a middleware sub-stack:

app.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl)
    next()
  },
  (req, res, next) => {
    console.log('Request Type:', req.method)
    next()
  }
)

Route middleware sub-stack

The following example demonstrates multiple middleware handlers for the same route:

app.get(
  '/user/:id',
  (req, res, next) => {
    console.log('ID:', req.params.id)
    next()
  },
  (req, res) => {
    res.send('User Info')
  }
)

The middleware above ends the request-response cycle using res.send(). Any matching routes defined after this will not execute unless next('route') is used.

Skipping to the next route

Call next('route') to skip the remaining middleware functions for the current route.

next('route') works only in middleware functions loaded using app.METHOD() or router.METHOD().

app.get(
  '/user/:id',
  (req, res, next) => {
    if (req.params.id === '0') {
      next('route')
    } else {
      next()
    }
  },
  (req, res) => {
    res.send('regular')
  }
)

app.get('/user/:id', (req, res) => {
  res.send('special')
})

Reusable middleware arrays

Middleware functions can also be grouped into arrays for better reusability:

function logOriginalUrl (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}

function logMethod (req, res, next) {
  console.log('Request Type:', req.method)
  next()
}

const logStuff = [logOriginalUrl, logMethod]

app.get('/user/:id', logStuff, (req, res) => {
  res.send('User Info')
})

Router-level middleware

Router-level middleware works the same way as application-level middleware, except it is bound to an instance of express.Router().

const router = express.Router()

Load router-level middleware using:

The following example demonstrates router-level middleware:

const express = require('express')
const app = express()
const router = express.Router()

// Runs for every request handled by this router
router.use((req, res, next) => {
  console.log('Time:', Date.now())
  next()
})

// Middleware sub-stack
router.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl)
    next()
  },
  (req, res, next) => {
    console.log('Request Type:', req.method)
    next()
  }
)

// Route-specific middleware
router.get(
  '/user/:id',
  (req, res, next) => {
    if (req.params.id === '0') {
      next('route')
    } else {
      next()
    }
  },
  (req, res) => {
    res.render('regular')
  }
)

// Special route handler
router.get('/user/:id', (req, res) => {
  console.log(req.params.id)
  res.render('special')
})

// Mount router
app.use('/', router)

Skipping out of a router

Use next('router') to exit the current router instance and pass control back to the main application.

const express = require('express')
const app = express()
const router = express.Router()

// Router guard middleware
router.use((req, res, next) => {
  if (!req.headers['x-auth']) {
    return next('router')
  }

  next()
})

router.get('/user/:id', (req, res) => {
  res.send('hello, user!')
})

// Fallback handler
app.use('/admin', router, (req, res) => {
  res.sendStatus(401)
})

Error-handling middleware

Error-handling middleware always requires four arguments:

(err, req, res, next)

Even if you do not use next, you must include it to ensure Express recognizes the function as error-handling middleware.

Example:

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

For more information, see: Error handling

Built-in middleware

Starting from Express 4.x, Express no longer depends on Connect. Middleware previously bundled with Express is now maintained in separate modules.

Express includes the following built-in middleware functions:

Third-party middleware

Third-party middleware can be used to add additional functionality to Express applications.

Install the required package using npm and load it either at the application level or router level.

The following example demonstrates the cookie-parser middleware:

npm install cookie-parser
const express = require('express')
const cookieParser = require('cookie-parser')

const app = express()

// Load cookie-parsing middleware
app.use(cookieParser())

For more commonly used middleware packages, see: Third-party middleware

Edit this page