Flask WSGI Middleware

Last Updated : 9 Jun, 2026

Middleware is used to process and modify requests and responses before they reach the application or client. While Flask provides request hooks such as before_request and after_request, WSGI (Web Server Gateway Interface) middleware operates at a lower level between the web server and the Flask application, allowing requests and responses to be intercepted and modified before reaching Flask. Some of the features are:

  • Logging
  • Authentication
  • Compression

Implementation

WSGI middleware follows a specific pattern:

  • It is implemented as a class that takes the Flask app as an argument.
  • The class must define a __call__ method, which processes the WSGI environment (incoming request details) and start_response (the response handler).
  • The modified request is then passed to the Flask app.

The following syntax demonstrates how to create and apply WSGI middleware to a Flask application.

class CustomWSGIMiddleware:
def __init__(self, app):
self.app = app # Wraps the Flask app

def __call__(self, environ, start_response):
# Modify request before passing it to Flask
print(f"Incoming request: {environ['REQUEST_METHOD']} {environ['PATH_INFO']}")

# Process the request with the Flask app
response = self.app(environ, start_response)

# Modify response if needed
return response

Now, to apply the above WSGI Middleware to a flask app use this:

app.wsgi_app = CustomWSGIMiddleware(app.wsgi_app)

Creating Custom WSGI Middleware

A simple WSGI middleware is a Python class that wraps around the Flask app and modifies requests or responses. Let's create a basic flask app and implement a custom wsgi middleware in it:

Python
class WSGILoggingMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        print(f"Incoming request: {environ['REQUEST_METHOD']} {environ['PATH_INFO']}")
        return self.app(environ, start_response)

from flask import Flask

app = Flask(__name__)
app.wsgi_app = WSGILoggingMiddleware(app.wsgi_app)  # Applying WSGI middleware

@app.route('/')
def home():
    return "Hello, WSGI Middleware!"

if __name__ == '__main__':
    app.run(debug=True)

Explanation:

  • __call__: This method intercepts the request before it reaches Flask.
  • environ: Contains request details like method and path.
  • start_response: A callable provided by the WSGI server used to start the HTTP response.
  • app.wsgi_app = WSGILoggingMiddleware(app.wsgi_app): Applies the middleware to Flask.

Output:

Run the application using command "python app.py" and the request details will be logged in the terminal. Below is the snapshot.

wsgi1
Request details in terminal

Using Third-Party WSGI Middleware

Instead of writing custom middleware, you can use pre-built WSGI middleware. A popular option is Werkzeug’s ProxyFix, which helps handle reverse proxy headers (like Nginx or a load balancer). Reverse proxies often modify headers like REMOTE_ADDR, HTTP_HOST, and SCRIPT_NAME, which Flask wouldn't recognize correctly by default.

Python
from werkzeug.middleware.proxy_fix import ProxyFix
from flask import Flask

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1)

@app.route('/')
def home():
    return "ProxyFix Middleware Applied!"

if __name__ == '__main__':
    app.run(debug=True)

Explanation:

  • ProxyFix(app.wsgi_app, x_for=1, x_host=1) configures Flask to trust specific proxy headers when the application is deployed behind a reverse proxy.
  • x_for=1 allows Flask to use the first X-Forwarded-For header to identify the client’s actual IP address.
  • x_host=1 enables Flask to determine the correct host using the X-Forwarded-Host header.

Demonstration

Start the app server using "python app.py" command in the terminal and then open postman and make a GET Request to the URL - "http://127.0.0.1:5000/". It will show the default client IP (localhost), as there are no proxy headers.

wsgi2
Status- 200 OK

Now add the following header to simulate a proxy an make GET Reques to the same URL-

  • Key: X-Forwarded-For
  • Value: 203.0.113.5

Flask will correctly recognize the forwarded IP as the client’s IP-

wsgi3
Proxy IP
Comment