Skip to content
Advertisement

Flask-CORS does not apply to responses returned by WSGI middleware

I have a Flask application that uses Flask-CORS, as well as a WSGI middleware that returns a custom response instead of the Flask app for some routes. For responses the middleware returns, Flask-CORS is not applied, so I’ve had to apply the CORS headers manually to that response.

class Middleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        request = Request(environ)

        if request.path == "/foo":
            res = Response("...", mimetype="application/json", status=403)
            # flask-cors is not applied, so I set headers manually
            res.access_control_allow_credentials = True
            res.access_control_allow_origin = "*"
            res.access_control_allow_methods = ["GET", "PUT", "DELETE", "PATCH", "OPTIONS", "POST", "HEAD"]
            return res(environ, start_response)

        return self.app(environ, start_response)  # flask-cors works here

app = Flask(__name__)
app.wsgi_app = Middleware(app)
CORS(app)

I tried reversing the order that the middleware and Flask-CORS are applied, but that didn’t change it.

app = Flask(__name__)
CORS(app)
app.wsgi_app = Middleware(app)

I don’t want to repeat what Flask-CORS does. How can I apply Flask-CORS to the response from the middleware?

Advertisement

Answer

Flask-CORS is a Flask extension. It works at the Flask application layer, that is it operates on a request that reaches the Flask application. Middleware applied to the application happens around the Flask application, the layer above what a Flask extension sees. The order you register the extension vs apply the middleware has no bearing on this, they are at different layers of the WSGI call stack.

When the request comes in, your middleware decides to return a response early and never calls down to the Flask application it wraps, so nothing about the Flask application executes, including the Flask-CORS extension on it. You can’t apply Flask-CORS to the middleware response because it doesn’t work at the same layer.

If you need CORS headers in the response returned by your middleware, you need to do what you did and set them yourself. If you want to avoid even this amount of duplication, you need to either do everything in Flask, or write a middleware that does CORS around this other middleware instead of the Flask-CORS extension.

To write the equivalent of your middleware inside the Flask stack, so that the Flask-CORS extension affects the response you generate, use before_request. A before_request function can return a response (or abort) to end view processing early and move on to response processing.

from flask import request, Response

@app.before_request
def some_users_403():
    if request.path == "/foo":
        return Response("...", status=403)
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement