forked from Github-Mirrors/canaille
feat: generic blueprint HTTP 404 error handler
This allows blueprint to handle 404 errors. This is not supported directly in Flask. https://flask.palletsprojects.com/en/stable/errorhandling/#handling However, the blueprint cannot handle 404 routing errors because the 404 occurs at the routing level before the blueprint can be determined.
This commit is contained in:
parent
e031b74684
commit
309511e91c
2 changed files with 28 additions and 9 deletions
|
@ -5,7 +5,9 @@ from urllib.parse import urlunsplit
|
|||
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import make_response
|
||||
from flask import request
|
||||
from werkzeug.exceptions import HTTPException
|
||||
from werkzeug.routing import BaseConverter
|
||||
|
||||
from canaille.app.i18n import gettext as _
|
||||
|
@ -107,3 +109,19 @@ def model_converter(model):
|
|||
return instance
|
||||
|
||||
return ModelConverter
|
||||
|
||||
|
||||
def redirect_to_bp_handlers(app, error):
|
||||
"""Find and execute blueprint handlers matching an error.
|
||||
|
||||
There is currently no way to make 404 handling generic:
|
||||
https://flask.palletsprojects.com/en/stable/errorhandling/#handling
|
||||
However, the blueprint cannot handle 404 routing errors because the
|
||||
404 occurs at the routing level before the blueprint can be determined.
|
||||
"""
|
||||
for bp in app.blueprints.values():
|
||||
if bp.url_prefix and request.path.startswith(bp.url_prefix):
|
||||
for type_, handler in bp.error_handler_spec[None][None].items():
|
||||
if type_ in (error.code, HTTPException): # pragma: no branch
|
||||
return make_response(handler(error))
|
||||
return None
|
||||
|
|
|
@ -40,15 +40,11 @@ if flask_themer:
|
|||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
# There is currently no way to make 404 handling generic
|
||||
# https://flask.palletsprojects.com/en/stable/errorhandling/#handling
|
||||
# However, the blueprint cannot handle 404 routing errors because the
|
||||
# 404 occurs at the routing level before the blueprint can be determined.
|
||||
if flask.request.path.startswith("/scim/"):
|
||||
from canaille.scim.endpoints import http_error_handler
|
||||
from canaille.app.flask import redirect_to_bp_handlers
|
||||
|
||||
return http_error_handler(error)
|
||||
return render_template("error.html", description=error, error_code=404), 404
|
||||
return redirect_to_bp_handlers(app, error) or render_template(
|
||||
"error.html", description=error, error_code=404
|
||||
), 404
|
||||
|
||||
@app.errorhandler(500)
|
||||
def server_error(error): # pragma: no cover
|
||||
|
@ -58,4 +54,9 @@ else: # pragma: no cover
|
|||
render_template = flask.render_template
|
||||
|
||||
def setup_themer(app):
|
||||
return
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(error):
|
||||
from canaille.app.flask import redirect_to_bp_handlers
|
||||
|
||||
if not redirect_to_bp_handlers(app, error):
|
||||
raise error
|
||||
|
|
Loading…
Reference in a new issue