Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global error handler for any exception

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 signal, as it is not allowed to modify the response (http://flask.pocoo.org/docs/0.10/signals/).

In contrast all signal handlers are executed in undefined order and do not modify any data.

I would prefer to not wrap the app.handle_exception function as that feels like internal API. I guess I'm after something like:

 @app.errorhandler()  def handle_global_error(e):      return "Global error" 

Note the errorhandler does not take any parameters, meaning it would catch all exceptions/status codes which does not have a specific error handler attached to them. I know I can use errorhandler(500) or errorhandler(Exception) to catch exceptions, but if I do abort(409) for example, it will still return a HTML response.

like image 865
joscarsson Avatar asked Mar 29 '15 16:03

joscarsson


People also ask

What is global exception handler?

The Global Exception Handler is a type of workflow designed to determine the project's behavior when encountering an execution error. Only one Global Exception Handler can be set per automation project.

What is exception Handler exception?

An exception handler is code that stipulates what a program will do when an anomalous event disrupts the normal flow of that program's instructions. An exception, in a computer context, is an unplanned event that occurs while a program is executing and disrupts the flow of its instructions.

Which annotation is used to handle exceptions globally?

The @ControllerAdvice is an annotation, to handle the exceptions globally.


2 Answers

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) 
like image 109
ThiefMaster Avatar answered Oct 01 '22 01:10

ThiefMaster


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

like image 34
lol Avatar answered Oct 01 '22 00:10

lol