Skip to main content

Code Around Every Handler

Middleware is code that runs around your handlers: before the request reaches them, after the response leaves them, or instead of them. Logging, authentication, rate limiting, compression — all middleware.

The same idea travels under three names: web frameworks say middleware, gRPC says interceptor, some ecosystems say filter. One concept, three vocabularies.

In Python, middleware is a function that takes a handler function and returns a wrapped one — exactly what Python's own @decorator syntax was made for, and exactly the Decorator pattern from the design patterns group. A stack of them behaves like a Chain of Responsibility.


A Logging Middleware

with_log wraps any handler function: it prints the request coming in, lets the handler work, and prints again on the way out. The handler itself stays completely unaware. functools.wraps keeps the wrapped function's name and docs visible — the same helper every Python decorator uses.

Wrap once, log everything

The wrapped handler serves two different paths and both get logged — the logging is written once, in the wrapper, not in every handler.

Prompt
Write a Python program with a with_log middleware that wraps a handler function, printing an arrow line with the method and path before calling it and a done line after. Wrap an app function that serves two paths, serve it on a free port, request both paths and print the responses.
Output: complete Python program
Wrap once, log everything

Middleware That Stops the Request

Middleware can also refuse: an auth check that finds no valid key answers 401 Unauthorized and never calls the next handler.

Chained as with_log(with_auth(report)), the request passes through the layers in order — and the response bubbles back out through them.

An auth layer in the chain

The request without a key is stopped by the auth layer with 401 — the handler never runs. With the key, the request passes the whole chain and reaches the data.

Prompt
Write a Python program with two chained middlewares: with_log printing the request, and with_auth checking the X-API-Key header and answering 401 without calling the next handler when the key is wrong. Wrap the handler as with_log(with_auth(report)), serve on a free port, then send one request without the key and one with it, printing both statuses and bodies.
Output: complete Python program