Flask middleware allows you to execute code before and after every request, making it perfect for cross-cutting concerns like authentication, logging, and CORS headers. Flask provides two key decorators for this: @app.before_request and @app.after_request.
The @app.before_request decorator registers a function that runs before any route handler is called. This is ideal for:
The @app.after_request decorator registers a function that runs after the route handler completes, receiving the response object as a parameter. This is perfect for:
Flask provides the g object (application context global) to store data that needs to be shared between before_request and after_request handlers within the same request. Unlike session data, g is request-scoped and automatically cleaned up after each request.
If a before_request function returns a response (like jsonify() with a status code), Flask skips the route handler and jumps directly to the after_request handlers. This makes it perfect for authentication middleware that can reject requests early.
Middleware runs in the order it's defined, so organize your handlers logically. Authentication should typically run before other processing, while response modification (like adding headers) should happen in after_request handlers.
1from flask import Flask, g, request, jsonify
2import time
3
4app = Flask(__name__)
5
6@app.before_request
7def start_timer():
8 g.start_time = time.time()
9 print(f"Starting request to {request.path}")
10
11@app.after_request
12def add_headers_and_log(response):
13 # Add a custom header to all responses
14 response.headers['X-Processing-Time'] = f"{time.time() - g.start_time:.3f}s"
15 print(f"Completed {request.method} {request.path}")
16 return response
17
18@app.route('/hello')
19def hello():
20 return jsonify({"message": "Hello, World!"})