Flask middleware on abort 401 causing a 500
Question: I have a middleware in my Flask app that is used to authenticate a JSON Web
Token coming in the header of the request and is checking to verify it, below
is my middleware class:

    
    
    class AuthMiddleware(object):
    
        def __init__(self, app):
            self.app = app
    
        def __call__(self, environ, start_response):
            path = environ.get('PATH_INFO')
            if path != '/authenticate' or path != '/token':
                token = environ.get('HTTP_X_ACCESS_TOKEN')
                verfied_token = verify_token(token)
                if verfied_token is False:
                    abort(401)
                elif verfied_token is True:
                    # payload = get_token_payload(token)
                    # check_permissions(payload)
                    pass
    
            return self.app(environ, start_response) 
    

`verify_token()` is a function that will return True or False, and if it
returns False, I want it to abort with an error 401. However, it aborts with
an error 500:

    
    
    127.0.0.1 - - [25/Mar/2015 11:37:25] "POST /role HTTP/1.1" 500 -
    Error on request:
    Traceback (most recent call last):
    File "/ENV/lib/python2.7/site-packages/werkzeug/serving.py", line 180, in run_wsgi
    execute(self.server.app)
    File "/ENV/lib/python2.7/site-packages/werkzeug/serving.py", line 168, in execute
    application_iter = app(environ, start_response)
    File "/ENV/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
    File "/middleware.py", line 24, in __call__
    return self.app(environ, start_response) 
    File "/ENV/lib/python2.7/site-packages/werkzeug/exceptions.py", line 605, in __call__
    raise self.mapping[code](*args, **kwargs)
    BadRequest: 400: Bad Request
    

In my views, I abort a 401 like it should, but here it seems to be a problem.
What should I do?


Answer: 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)
    

