Express.js - Middlewares

Express.js - Middlewares

·

3 min read

Just as the document of Express.js says: an Express application is essentially a series of middleware function calls. So middleware is actually the key of this framework. Let's explore its usage in this article.

The basics

Middleware functions are just plain callback functions. We define these functions, pass them to express, and express will call these functions at a pre-defined time and order.

The function accepts 3 parameters, request, response and next. The request and response are just the same object in the router callback function. And the third parameter next is a function which can be called inside the middleware function to control the flow of the middlewares execution.

A simple example is like below.

const express = require("express");
const app = express();

// define middleware function
const middleware = (req, res, next) => {
    console.log("middleware");
    next();
}

// pass it to express
app.use(middleware);

app.get("/", (req, res) => {
    console.log("handling request")
    res.send("hello");
});

app.listen(3000, () => {
    console.log("app started");
});

When receiving a request, the middleware function will be called first. After the next function is called, the router callback will be called.

With this kind of execution, we can split logics into middlewares and writer cleaner code.

Order of execution

The middlewares should be defined before the router they follow a chain-style execution order. Take below code as an example.

const express = require("express");
const app = express();

// pass mutiple middlewares together is ok
app.use(
    (req, res, next) => {
        console.log("enter m1");
        next();
        console.log("leave m1");
    },
    (req, res, next) => {
        console.log("enter m2");
        next();
        console.log("leave m2");
    },
    (req, res, next) => {
        console.log("enter m3");
        next();
        console.log("leave m3");
    },
);

app.get("/", (req, res) => {
    console.log("handling request");
    res.send("hello");
});

app.listen(3000, () => {
    console.log("app started");
});

The execution log is like blew.

enter m1
enter m2
enter m3
handling request
leave m3
leave m2
leave m1

Within this execution order, we can do all kinds of operations. For example, we can log the access time. We can prepare user input in certain format and pass it to router callbacks. We can auth users and return the result directly. And so on...

Different level

In above code, the middlewares are all mounted on the application object. This is call application-level middleware. We can also have them mounted on the router object, and this is call router-level middleware. Same example for router is like below.

const express = require("express");
const app = express();

const router = express.Router()

router.use(
    (req, res, next) => {
        console.log("enter m1");
        next();
        console.log("leave m1");
    },
    (req, res, next) => {
        console.log("enter m2");
        next();
        console.log("leave m2");
    },
    (req, res, next) => {
        console.log("enter m3");
        next();
        console.log("leave m3");
    },
);

router.get("/", (req, res) => {
    console.log("handling request");
    res.send("hello");
});

app.use("/user", router);

app.listen(3000, () => {
    console.log("app started");
});

The middlewares can also be mounted on a specific path.

app.use("/user", (req, res, next) => {
    console.log("enter middleware");
    next();
    console.log("leave middleware");
});

Existing middlewares

Because the design of middleware, not only we can write our own middlewares, but also it allows developer to share the middlewares.

There are built-in middlewares in express like express.static, express.json and express.urlencoded. And a whole bunch of third-party middlewares we can chek from this page.

For example, this built-in static middleware can be used to server static files easily.

const express = require("express");
const app = express();

app.use(express.static("./images"))

app.get("/user", (req, res) => {
    res.end("hello");

})

app.listen(3000, () => {
    console.log("app started");
});

So we can access static files from this images folder like this http://localhost:3000/1.png.