Skip to content

Writing middleware

Aaron edited this page Mar 17, 2023 · 1 revision

Writing middleware for use in Express app

Overview

Middleware functions are functions that have access to the request object, the response object, and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

Middleware functions can perform the following tasks:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware in the stack.

The current middleware function could call the next() function to pass control to next middleware function. If the next() function is not used, it will be automatically ran at the end of the middleware.

Example

Here is an example of a simple “Hello World” Express application. The remainder of this article will define and add three middleware functions to the application: one called myLogger that prints a simple log message, one called requestTime that displays the timestamp of the HTTP request, and one called validateCookies that validates incoming cookies.

from express import express

app = express()

@app.get("/")
def home(req, res):
    res.send("Hello World!")

app.listen(3000)

Middleware function myLogger

Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it.

def myLogger(req, res, next):
    print("LOGGED")
    next()

To load the middleware function as a global middleware, call app.use(), specifying the middleware function. Example:

from express import express

app = express()

def myLogger(req, res, next):
    print("LOGGED")
    next()

@app.get("/")
def home(req, res):
    res.send("Hello World!")

app.use(myLogger)

app.listen(3000)

Every time the app receives a request, it prints the message “LOGGED” to the terminal. The order of middleware loading is important: middleware functions that are loaded first are also executed first. The middleware function myLogger simply prints a message, then passes on the request to the next middleware function in the stack by calling the next() function.

Middleware function requestTime

Next, we’ll create a middleware function called “requestTime” and add a property called requestTime to the request object.

import time

def requestTime(req, res, next):
    req.requestTime = time.time()
    next()
    print(f"Request handling took {time.time() - req.requestTime} seconds")

The app now uses the requestTime middleware function. Also, the callback function of the root path route uses the property that the middleware function adds to req (the request object).

import time
from express import express

app = express()

def requestTime(req, res, next):
    req.requestTime = time.time()
    next()
    print(f"Request handling took {time.time() - req.requestTime} seconds")

@app.get("/")
def home(req, res):
    res.send(f"Requested at: {req.requestTime}")

app.use(requestTime)

app.listen(3000)

When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.

Middleware function validateCookies

Finally, we’ll create a middleware function that validates incoming cookies and sends a 400 response if cookies are invalid. Here’s an example middleware that validates cookies with an external service:

def validateCookies(req, res, next):
    success = doValidate(req.cookie("authentication"))
    if not success:
        res.status(400).send("Forbidden!")

Here we use the validateCookies middleware to validate the cookies parsed by express.py. validateCookies will return a HTTP 400 error with the message "Forbidden!" when they the authentication is invalid. Otherwise it will show the secret content:

from express import express

app = express()

def validateCookies(req, res, next):
    success = doValidate(req.cookie("authentication"))
    if not success:
        res.status(400).send("Forbidden!")

@app.get("/", None, validateCookies)
def home(req, res):
    res.send("Very secret message for a very secure endpoint!!!")

app.listen(3000)

Because you have access to the request object, the response object, the next middleware function in the stack, and the whole of Python, the possibilities with middleware functions are endless.