The Python Oracle

Flask middleware on abort 401 causing a 500

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: A Thousand Exotic Places Looping v001

--

Chapters
00:00 Flask Middleware On Abort 401 Causing A 500
01:04 Accepted Answer Score 16
02:15 Thank you

--

Full question
https://stackoverflow.com/questions/2926...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #flask #middleware #abort

#avk47



ACCEPTED ANSWER

Score 16


The middleware you've shown runs some other code and then calls the wrapped Flask application. However, abort raises exceptions that Flask handles, but aren't handled by WSGI directly. Since you're not in the Flask application yet, it can't handle the exception.

A much easier way would be to do this check inside the Flask app. Create a before_request handler that does basically the same thing as the middleware, except you can use flask.request rather than needing to parse the path and headers yourself.

from flask import request, abort

@app.before_request
def check_auth_token():
    if request.path in ('/authenticate', '/token'):
        return

    token = request.headers.get('X-ACCESS-TOKEN')

    if not verify_token(token):
        abort(401)

    check_permissions(get_token_payload(token))

If you do want to use WSGI middleware for this, you need to create the response yourself. Conveniently, Werkzeug's exceptions behave like WSGI applications, so it's straightforward to use them.

from werkzeug.exceptions import Unauthorized

# in place of abort(401) in the middleware
return Unauthorized()(environ, start_response)

You can also use abort still by catching the exceptions it raises (which, again, are WSGI applications).

from werkzeug.exceptions import abort, HTTPException
# werkzeug.exceptions.abort is the same as flask.abort

try:
    abort(401)
except HTTPException as e:
    return e(environ, start_response)