From a56d857dc1f6dbc25819a4af116139a2f3e14a68 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 15 Jun 2023 11:07:18 +0300 Subject: Move generic exception handler. Move the generic exception handler to the `wqflask.app_errors` module and register it with the `register_error_handler` method. --- wqflask/wqflask/__init__.py | 5 ++++- wqflask/wqflask/app_errors.py | 39 +++++++++++++++++++++++++++++++++++++-- wqflask/wqflask/views.py | 35 ----------------------------------- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py index 140e94ad..654fe028 100644 --- a/wqflask/wqflask/__init__.py +++ b/wqflask/wqflask/__init__.py @@ -6,6 +6,7 @@ from urllib.parse import urljoin, urlparse import redis import jinja2 +import werkzeug from flask_session import Session from authlib.integrations.requests_client import OAuth2Session from flask import g, Flask, flash, session, url_for, redirect, current_app @@ -79,7 +80,9 @@ app.register_blueprint(jobs_bp, url_prefix="/jobs") app.register_blueprint(oauth2, url_prefix="/oauth2") from wqflask.decorators import AuthorisationError -from wqflask.app_errors import handle_authorisation_error +from wqflask.app_errors import ( + handle_generic_exceptions, handle_authorisation_error) +app.register_error_handler(Exception, handle_generic_exceptions) app.register_error_handler(AuthorisationError, handle_authorisation_error) server_session = Session(app) diff --git a/wqflask/wqflask/app_errors.py b/wqflask/wqflask/app_errors.py index 18b29841..c24fc9be 100644 --- a/wqflask/wqflask/app_errors.py +++ b/wqflask/wqflask/app_errors.py @@ -1,11 +1,46 @@ """Handle errors at the application's top-level""" +import datetime +import traceback -from flask import current_app, render_template +import werkzeug +from flask import request, render_template, current_app as app from wqflask.decorators import AuthorisationError +def handle_generic_exceptions(exc): + err_msg = str(exc) + now = datetime.datetime.utcnow() + time_str = now.strftime('%l:%M%p UTC %b %d, %Y') + # get the stack trace and send it to the logger + exc_type, exc_value, exc_traceback = sys.exc_info() + formatted_lines = (f"{request.url} ({time_str}) \n" + f"{traceback.format_exc()}") + _message_templates = { + werkzeug.exceptions.NotFound: ( + f"404: Not Found: {time_str}: {request.url}"), + werkzeug.exceptions.BadRequest: ( + f"400: Bad Request: {time_str}: {request.url}"), + werkzeug.exceptions.RequestTimeout: ( + f"408: Request Timeout: {time_str}: {request.url}") + } + # Default to the lengthy stack trace! + app.logger.error(_message_templates.get(exc_type, formatted_lines)) + # Handle random animations + # Use a cookie to have one animation on refresh + animation = request.cookies.get(err_msg[:32]) + if not animation: + animation = random.choice([fn for fn in os.listdir( + "./wqflask/static/gif/error") if fn.endswith(".gif")]) + + resp = make_response(render_template("error.html", message=err_msg, + stack={formatted_lines}, + error_image=animation, + version=app.config["GN_VERSION"])) + resp.set_cookie(err_msg[:32], animation) + return resp + def handle_authorisation_error(exc: AuthorisationError): """Handle AuthorisationError if not handled anywhere else.""" - current_app.logger.error(exc) + app.logger.error(exc) return render_template( "authorisation_error.html", error_type=type(exc).__name__, error=exc) diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py index e7a32d34..7cbcb3b8 100644 --- a/wqflask/wqflask/views.py +++ b/wqflask/wqflask/views.py @@ -108,41 +108,6 @@ from wqflask.oauth2.checks import user_logged_in Redis = get_redis_conn() -@app.errorhandler(Exception) -def handle_generic_exceptions(e): - import werkzeug - err_msg = str(e) - now = datetime.datetime.utcnow() - time_str = now.strftime('%l:%M%p UTC %b %d, %Y') - # get the stack trace and send it to the logger - exc_type, exc_value, exc_traceback = sys.exc_info() - formatted_lines = (f"{request.url} ({time_str}) \n" - f"{traceback.format_exc()}") - _message_templates = { - werkzeug.exceptions.NotFound: ("404: Not Found: " - f"{time_str}: {request.url}"), - werkzeug.exceptions.BadRequest: ("400: Bad Request: " - f"{time_str}: {request.url}"), - werkzeug.exceptions.RequestTimeout: ("408: Request Timeout: " - f"{time_str}: {request.url}")} - # Default to the lengthy stack trace! - app.logger.error(_message_templates.get(exc_type, - formatted_lines)) - # Handle random animations - # Use a cookie to have one animation on refresh - animation = request.cookies.get(err_msg[:32]) - if not animation: - animation = random.choice([fn for fn in os.listdir( - "./wqflask/static/gif/error") if fn.endswith(".gif")]) - - resp = make_response(render_template("error.html", message=err_msg, - stack={formatted_lines}, - error_image=animation, - version=GN_VERSION)) - resp.set_cookie(err_msg[:32], animation) - return resp - - @app.route("/authentication_needed") def no_access_page(): return render_template("new_security/not_authenticated.html") -- cgit v1.2.3