Express Middleware
When an Express server receives an HTTP request, it executes a list of middleware functions. The middleware functions are responsible for handling the request and crafting a response.
You will usually see middleware defined as a function with 3 parameters: req
, res
, and next
. The biggest exception to this rule is error handling middleware.
To add a middleware function to your Express app, you call app.use()
.
const app = require('express')();
app.use((req, res, next) => {
req; // The request
res; // The response
next; // A function that you must call to trigger the next middleware
});
Under the hood, when you call app.use()
, Express adds your function to
its internal middleware stack. Express executes middleware in the order they're
added, so if you call app.use(fn1); app.use(fn2);
, Express will execute fn1
before fn2
.
Middleware vs Route Handlers
Suppose you have a simple Express server that responds to GET requests with the string 'Hello, World' as shown below.
const app = require('express')();
app.get('/', function routeHandler(req, res) {
res.send('Hello, World');
});
In Express, a route handler is just a special type of middleware that never
calls next()
. You could also write a middleware that does the same thing.
app.use(function(req, res, next) {
// Do nothing if the request isn't `GET /`
if (req.method !== 'GET' || req.url !== '/') {
return next();
}
res.send('Hello, World');
});
Routing
The app.use()
function takes 2
parameters: an optional path
, and a middleware function callback
. If the first parameter to app.use()
is
a string, Express will only execute the corresponding middleware function if
the URL matches.
// Express will only call `middleware()` if `req.url` is equal to '/'
app.use('/', function middleware(req, res, next) {
// Do nothing if the request isn't a 'GET' request
if (req.method !== 'GET') {
return next();
}
res.send('Hello, World');
});
The next()
Function
If you have multiple middleware functions, you need to make sure your middleware
either calls next()
or send a response. If you write Express middleware,
this is your responsibility. Express will not throw an error if your middleware
doesn't call next()
, it will simply hang.
// If you open this page in Chrome, it will just keep loading forever.
app.use('/', function middleware(req, res, next) {
console.log('Test');
});
In general, it is best practice to call next()
unless you explicitly do not
want the rest of the middleware stack to run. Calling next()
if there's no
more middleware is perfectly fine.
// It is OK to call `next()` even if there's no more middleware.
app.use((req, res, next) => {
res.send('Hello, World');
next();
});
If you call next()
with a parameter, Express will treat that parameter as an
error and trigger error handling middleware. The below middleware will cause Express to respond with an HTTP 500 and a stack trace.
app.use((req, res, next) => {
next(new Error('Fail!'));
});
If you open the above middleware in Chrome, you'll see something like this:
Espresso supports:
- Route handlers, like `app.get()` and `app.post()`
- Express-compatible middleware, like `app.use(require('cors')())`
- Express 4.0 style subrouters
Get the tutorial and master Express today!