pythonpython-3.xflaskpython-decoratorsflask-restful

how to catch all exceptions raised in flask_restful app


I do have simple restful app with Flask-Restful

from flask import Flask
from flask_restful import Api

app = Flask(__name__)
...
api = Api(app)

api.add_resource(ContactList, "/contacts")


if __name__ == '__main__':
    from object_SQLAlchemy import db
    db.init_app(app)
    app.run(port=5000)


class Contact(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument(
        'contact_no',
        type=str,
        required=True,
        help="This field cannot be left blank"
    )

    @throttling.Throttle("10/m", strategy=2)
    def get(self, name):
        contact = Contacts.findbyname(name)
        if contact:
            return contact.json()
        return {"message": "Contact does not exist."}, 404

'get' method is decorated with my implementation of throttling (https://github.com/scgbckbone/RESTAPI/blob/master/resources/utils/throttling.py). What is important is that the throttling decorator raises exceptions on some occasions - most importantly when limit is reached. I would like to be able to catch that exception and return some reasonable json message.

But none of following works:

from ..app_alchemy import api, app


@api.errorhandler(Exception)
def handle_error(e):
    return {"error": str(e)}


@app.errorhandler(500)
def handle_error_app(e):
    return {"error": str(e.args[0])}


@app.handle_exception(Exception)
def handle_it_app(e):
    return {"error": str(e.args[0])}


@api.handle_exception(Exception)
def handle_it(e):
   return {"error": str(e.args[0])}

I'm still getting back default message

{"message": "Internal Server Error"}

Do I use errorhandlers correctly, or is the issue related to the use of decorator? I truly have no idea.


Solution

  • There is a Flask-Restful built-in tool for handling exceptions, you can pass a dictionary of exception classes and response fields to Api constructor:

    api = Api(app, errors={
        'Exception': {
            'status': 400,
            'message': 'bad_request',
            'some_description': 'Something wrong with request'
        }
    })
    

    Status is 500 by default, all other field are just turned to JSON and sent in response.

    There is a major downside: you cannot use exception text as error message. There is an open issue for it.