I create a Python/Flask application with the following code in main.py:
import json
from flask import Flask, jsonify
from werkzeug.exceptions import HTTPException, default_exceptions
from blueprints import test
def create_app(config_filename=None) -> Flask:
"""Application factory function
"""
app = Flask(__name__, instance_relative_config=True)
if config_filename:
app.config.from_pyfile(config_filename)
for exc in default_exceptions:
app.register_error_handler(exc, handle_error)
register_blueprints(app)
return app
def handle_error(error):
code = 500
if isinstance(error, HTTPException):
code = error.code
return jsonify(error='error', code=code)
def register_blueprints(app: Flask):
"""Register blueprints
"""
app.register_blueprint(test.bp)
def handle_exception(ex: HTTPException):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = ex.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": ex.code,
"error": ex.name,
"message": ex.description,
})
response.content_type = "application/json"
return response
if __name__ == '__main__':
main_app = create_app()
main_app.run(host='0.0.0.0', port=80, debug=True, threaded=False)
and the source code of the test.py blueprint is:
from flask import Blueprint, jsonify, request
from werkzeug.exceptions import HTTPException, default_exceptions
bp = Blueprint('blabla', __name__)
@bp.route('/blabla', methods=['POST'])
def blabla():
"""Test blueprint
"""
raise MyException()
class MyException(HTTPException):
code = 409
name = 'My Exception'
description = 'My Exception'
unfortunately when i execute the endpoint, the exception is not handled by the method, defined in the main.py
I even decided and tried to register error handlers in the blueprint, but the result is the same - the exception is not handled by the methods.
Here is the modified test.py
from flask import Blueprint, jsonify, request
from werkzeug.exceptions import HTTPException, default_exceptions
bp = Blueprint('blabla', __name__)
@bp.errorhandler(409)
def error_handler(e):
return handle_error(e)
@bp.route('/blabla', methods=['POST'])
def blabla():
"""Test blueprint
"""
raise MyException()
def handle_error(error):
code = 500
if isinstance(error, HTTPException):
code = error.code
return jsonify(error='error', code=code)
class MyException(HTTPException):
code = 409
name = 'My Exception'
description = 'My Exception'
Can someone tell me what is my error? Why the exception is not handled by the error methods?
CodePudding user response:
This example is directly from flask, which has slight differences in terms of your code, for example, in @app.errorhandler(404)
decorator they check request users as follows request.path.startswith('')
, maybe this is not the source of your error but I recommend that you carefully read the examples and instructions to handle errors using blue print error handlers.
from flask import jsonify, render_template
# at the application level
# not the blueprint level
@app.errorhandler(404)
def page_not_found(e):
# if a request is in our blog URL space
if request.path.startswith('/blog/'):
# we return a custom blog 404 page
return render_template("blog/404.html"), 404
else:
# otherwise we return our generic site-wide 404 page
return render_template("404.html"), 404
@app.errorhandler(405)
def method_not_allowed(e):
# if a request has the wrong method to our API
if request.path.startswith('/api/'):
# we return a json saying so
return jsonify(message="Method Not Allowed"), 405
else:
# otherwise we return a generic site-wide 405 page
return render_template("405.html"), 405
CodePudding user response:
Actually it came out, that the error handler has to be registered after the blueprints:
def register_blueprints(app: Flask):
app.register_blueprint(test.bp)
app.register_error_handler(HTTPException, handle_exception)
def handle_exception(ex: HTTPException):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = ex.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": ex.code,
"error": ex.name,
"message": ex.description,
})
response.content_type = "application/json"
return response