I want to write middleware for Flask that changes the data in an HTML response. In Django, I could use a Middleware
class and access response.content
to change the content. How can I access and modify the response content in Flask or WSGI middleware?
class Middleware:
def __init__(self, get_response=None):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
self.process_response(request, response)
return response
def process_response(self, request, response):
html = response.content.decode('utf-8')
# do stuff with the HTML
return response
The closest equivalent of Django's "middleware" in Flask is Flask's before_request
and after_request
functions. They can introspect and modify the request and response at the same layer as the Flask app.
To get the response content, access response.get_data(as_text=True)
in an after_request
function. The function must return a response, either modify response.data
directly or create a new response with app.make_response(new_data)
. You can also modify any other properties of the resonse.
from flask import request
@app.before_request
def modify_incoming():
if {some test on request}:
...
# can return app.make_response() to end the request early
@app.after_request
def modify_outgoing(response):
html = response.get_data(as_text=True)
response.data = {modify html}
return response
WSGI middleware (which can be used with any WSGI framework, including Django) is at a layer outside the app itself, so you would need to either use the basic interface provided by the WSGI spec. Werkzeug's utilities may be useful at this lower layer.
class ModifyHTMLMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# can modify environ to affect what the wrapped application sees
app_iter = self.app(environ, start_response)
# decode and encode need to use the appropriate codec
html = b"".join(app_iter).decode("utf8")
# modify html
return [html.encode("utf8")]