100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Flask Middleware and Hooks

Using before_request, after_request, teardown hooks, and WSGI middleware to run shared logic like timing, headers, cleanup, and proxy handling around every request.

Advanced FlaskIntermediate10 min readJul 10, 2026
Analogies

Request Lifecycle Hooks in Flask

Flask exposes hooks that run at defined points in the request/response cycle: before_request runs before the view function, after_request runs after a successful view (and can modify the response), teardown_request always runs even if an exception occurred, and teardown_appcontext runs when the application context is popped. These hooks are commonly used for tasks like opening a database connection, injecting request timing headers, or logging every request uniformly without repeating code in every view.

🏏

Cricket analogy: Before every over, the umpire checks the bowler's run-up mark and field placements are legal, a standardized check that runs regardless of which bowler is up, just as before_request runs before every view function uniformly.

after_request, teardown_request, and Response Modification

after_request receives the response object and must return it (possibly modified), making it ideal for adding headers like X-Request-ID or Content-Security-Policy uniformly. Unlike after_request, teardown_request and teardown_appcontext are guaranteed to run even when an exception propagates out of the view, which makes them the correct place to close database sessions or release connections regardless of whether the request succeeded or failed.

🏏

Cricket analogy: The scorer updates the scoreboard with the final tally after every over concludes, always tagging it with the over number, just as after_request stamps the response with a request ID before it's sent.

python
import time
import uuid
from flask import Flask, g, request

app = Flask(__name__)

@app.before_request
def start_timer():
    g.start_time = time.time()
    g.request_id = str(uuid.uuid4())

@app.after_request
def add_headers(response):
    response.headers["X-Request-ID"] = g.request_id
    elapsed = time.time() - g.start_time
    response.headers["X-Response-Time-ms"] = f"{elapsed * 1000:.1f}"
    return response

@app.teardown_appcontext
def close_db(exception=None):
    db_session = g.pop("db_session", None)
    if db_session is not None:
        db_session.close()

WSGI Middleware vs Flask Hooks

Flask's before/after_request hooks operate within Flask's own request context and have access to g, request, and session, whereas WSGI middleware (functions wrapping app.wsgi_app) operate at a lower level, before Flask has even built its request context, and are the right tool for concerns like reverse-proxy header handling (ProxyFix) or enforcing HTTPS redirects that need to happen before Flask-specific objects exist.

🏏

Cricket analogy: Ground security screens every spectator entering the stadium before they even reach their specific seating section, a check that happens outside the match itself, just as WSGI middleware runs before Flask's request context is even built.

werkzeug.middleware.proxy_fix.ProxyFix is commonly applied as app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1) when running behind a reverse proxy like Nginx, so request.remote_addr and request.is_secure reflect the original client, not the proxy.

before_request hooks registered on a blueprint only run for requests routed to that blueprint's endpoints, while before_request hooks registered directly on the app run for every request — mixing these up silently causes hooks to be skipped for certain routes.

  • before_request runs before every view function; after_request runs after and must return the response.
  • teardown_request and teardown_appcontext always run, even after an unhandled exception, making them correct for cleanup.
  • The g object is the standard place to stash per-request state like timers or request IDs for hooks to share.
  • WSGI middleware wraps app.wsgi_app and runs before Flask builds its request context, suited to proxy/header concerns.
  • ProxyFix is the standard middleware for correctly reading client IP and scheme behind a reverse proxy.
  • Blueprint-registered before_request hooks only fire for that blueprint's routes, unlike app-level hooks which fire for all requests.
  • Choosing between a Flask hook and WSGI middleware depends on whether Flask-specific objects (request, g, session) are needed.

Practice what you learned

Was this page helpful?

Topics covered

#Python#FlaskStudyNotes#WebDevelopment#FlaskMiddlewareAndHooks#Flask#Middleware#Hooks#Request#StudyNotes#SkillVeris