Global error handler for any exception

前端 未结 6 1609
旧时难觅i
旧时难觅i 2020-12-04 18:07

Is there a way to add a global catch-all error handler in which I can change the response to a generic JSON response?

I can\'t use the got_request_exception

相关标签:
6条回答
  • 2020-12-04 18:12

    You can use @app.errorhandler(Exception):

    Demo (the HTTPException check ensures that the status code is preserved):

    from flask import Flask, abort, jsonify
    from werkzeug.exceptions import HTTPException
    
    app = Flask('test')
    
    @app.errorhandler(Exception)
    def handle_error(e):
        code = 500
        if isinstance(e, HTTPException):
            code = e.code
        return jsonify(error=str(e)), code
    
    @app.route('/')
    def index():
        abort(409)
    
    app.run(port=1234)
    

    Output:

    $ http get http://127.0.0.1:1234/
    HTTP/1.0 409 CONFLICT
    Content-Length: 31
    Content-Type: application/json
    Date: Sun, 29 Mar 2015 17:06:54 GMT
    Server: Werkzeug/0.10.1 Python/3.4.3
    
    {
        "error": "409: Conflict"
    }
    
    $ http get http://127.0.0.1:1234/notfound
    HTTP/1.0 404 NOT FOUND
    Content-Length: 32
    Content-Type: application/json
    Date: Sun, 29 Mar 2015 17:06:58 GMT
    Server: Werkzeug/0.10.1 Python/3.4.3
    
    {
        "error": "404: Not Found"
    }
    

    If you also want to override the default HTML exceptions from Flask (so that they also return JSON), add the following before app.run:

    from werkzeug.exceptions import default_exceptions
    for ex in default_exceptions:
        app.register_error_handler(ex, handle_error)
    

    For older Flask versions (<=0.10.1, i.e. any non-git/master version at the moment), add the following code to your application to register the HTTP errors explicitly:

    from werkzeug import HTTP_STATUS_CODES
    for code in HTTP_STATUS_CODES:
        app.register_error_handler(code, handle_error)
    
    0 讨论(0)
  • 2020-12-04 18:13

    If the Exceptions doesn't work, you may try app.register_error_handler (or use app.errorhandler in a non-decorator way)

    Source: https://github.com/pallets/flask/issues/1837

    0 讨论(0)
  • 2020-12-04 18:15

    Based on Plain (non-HTML) error pages in REST api

    I wanted to return json without changing any of my code at all, so I just added the following on the top of my code

    @app.errorhandler(500)
    def error_500(exception):
        return jsonify({"error": str(exception)}), 500, {'Content-Type': 'application/json'}
    
    @app.errorhandler(400)
    def error_400(exception):
        return jsonify({"error": str(exception)}), 400, {'Content-Type': 'application/json'}
    
    0 讨论(0)
  • 2020-12-04 18:23

    Far from elegant, but the following works for tying all subclasses of HTTPException to a single error handler:

    from flask import jsonify
    from werkzeug.exceptions import HTTPException
    
    def handle_error(error):
        code = 500
        if isinstance(error, HTTPException):
            code = error.code
        return jsonify(error='error', code=code)
    
    for cls in HTTPException.__subclasses__():
        app.register_error_handler(cls, handle_error)
    
    0 讨论(0)
  • 2020-12-04 18:35

    This is Flask 0.12 compatible, and a very good solution to the problem (it allows one to render errors in JSON or any other format)

    from functools import wraps
    from flask import Flask, redirect, jsonify
    app = Flask(__name__)
    
    def get_http_exception_handler(app):
        """Overrides the default http exception handler to return JSON."""
        handle_http_exception = app.handle_http_exception
        @wraps(handle_http_exception)
        def ret_val(exception):
            exc = handle_http_exception(exception)    
            return jsonify({'code':exc.code, 'message':exc.description}), exc.code
        return ret_val
    
    # Override the HTTP exception handler.
    app.handle_http_exception = get_http_exception_handler(app)
    

    https://github.com/pallets/flask/issues/671#issuecomment-12746738

    0 讨论(0)
  • 2020-12-04 18:35

    A cleaner way to implement this in Flask >=0.12 would be to explicitly register the handler for every Werkzeug exception:

    from flask import jsonify
    from werkzeug.exceptions import HTTPException, default_exceptions
    
    app = Flask('test')
    
    def handle_error(error):
        code = 500
        if isinstance(error, HTTPException):
            code = error.code
        return jsonify(error='error', code=code)
    
    for exc in default_exceptions:
        app.register_error_handler(exc, handle_error)
    
    0 讨论(0)
提交回复
热议问题