diff options
author | Frederick Muriuki Muriithi | 2025-07-09 09:36:21 -0500 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2025-07-09 09:36:21 -0500 |
commit | 72fcbb0fc1e0c347c827042722c68ab5efbcfb2e (patch) | |
tree | be8752f36cda38c628d87f38e693e0d6e7824660 | |
parent | f703399bdda4d4f4362653bdea4190804c3590d5 (diff) | |
download | gn-auth-72fcbb0fc1e0c347c827042722c68ab5efbcfb2e.tar.gz |
Move error handling into separate package.
-rw-r--r-- | gn_auth/errors/__init__.py (renamed from gn_auth/errors.py) | 45 | ||||
-rw-r--r-- | gn_auth/errors/http/__init__.py | 13 | ||||
-rw-r--r-- | gn_auth/errors/http/http_4xx_errors.py | 31 | ||||
-rw-r--r-- | gn_auth/errors/http/http_5xx_errors.py | 7 | ||||
-rw-r--r-- | gn_auth/errors/tracing.py | 18 |
5 files changed, 88 insertions, 26 deletions
diff --git a/gn_auth/errors.py b/gn_auth/errors/__init__.py index 4b6007a..533a842 100644 --- a/gn_auth/errors.py +++ b/gn_auth/errors/__init__.py @@ -1,38 +1,26 @@ """Handle application level errors.""" +import logging import traceback -from werkzeug.exceptions import NotFound -from flask import Flask, request, jsonify, current_app, render_template +from werkzeug.exceptions import NotFound, HTTPException +from flask import (Flask, + request, + jsonify, + render_template) from gn_auth.auth.errors import AuthorisationError -def add_trace(exc: Exception, errobj: dict) -> dict: - """Add the traceback to the error handling object.""" - current_app.logger.error("Endpoint: %s\n%s", - request.url, - traceback.format_exception(exc)) - return { - **errobj, - "error-trace": "".join(traceback.format_exception(exc)) - } +from .tracing import add_trace +from .http import http_error_handlers -def page_not_found(exc): - """404 handler.""" - current_app.logger.error(f"Page '{request.url}' was not found.", exc_info=True) - content_type = request.content_type - if bool(content_type) and content_type.lower() == "application/json": - return jsonify(add_trace(exc, { - "error": exc.name, - "error_description": (f"The page '{request.url}' does not exist on " - "this server.") - })), exc.code +logger = logging.getLogger(__name__) - return render_template("404.html", page=request.url), exc.code +__all__ = ["register_error_handlers"] def handle_general_exception(exc: Exception): """Handle generic unhandled exceptions.""" - current_app.logger.error("Error occurred!", exc_info=True) + logger.error("Error occurred!", exc_info=True) content_type = request.content_type if bool(content_type) and content_type.lower() == "application/json": exc_args = [str(x) for x in exc.args] @@ -51,19 +39,24 @@ def handle_general_exception(exc: Exception): def handle_authorisation_error(exc: AuthorisationError): """Handle AuthorisationError if not handled anywhere else.""" - current_app.logger.error("Error occurred!", exc_info=True) - current_app.logger.error(exc) + logger.error("Error occurred!", exc_info=True) + logger.error(exc) return jsonify(add_trace(exc, { "error": type(exc).__name__, "error_description": " :: ".join(exc.args) })), exc.error_code __error_handlers__ = { - NotFound: page_not_found, Exception: handle_general_exception, AuthorisationError: handle_authorisation_error } + + def register_error_handlers(app: Flask): """Register ALL defined error handlers""" + _handlers = { + **__error_handlers__, + **http_error_handlers() + } for class_, error_handler in __error_handlers__.items(): app.register_error_handler(class_, error_handler) diff --git a/gn_auth/errors/http/__init__.py b/gn_auth/errors/http/__init__.py new file mode 100644 index 0000000..f4164d1 --- /dev/null +++ b/gn_auth/errors/http/__init__.py @@ -0,0 +1,13 @@ +"""HTTP error handlers.""" + +from .http_4xx_errors import http_4xx_error_handlers +from .http_5xx_errors import http_5xx_error_handlers + +__all__ = ["http_error_handlers"] + +def http_error_handlers() -> dict: + """Return *ALL* HTTP error handlers.""" + return { + **http_4xx_error_handlers(), + **http_5xx_error_handlers() + } diff --git a/gn_auth/errors/http/http_4xx_errors.py b/gn_auth/errors/http/http_4xx_errors.py new file mode 100644 index 0000000..704f11b --- /dev/null +++ b/gn_auth/errors/http/http_4xx_errors.py @@ -0,0 +1,31 @@ +"""Handlers for HTTP 4** errors""" +import logging +from werkzeug.exceptions import NotFound + +from flask import request, jsonify, render_template + +from gn_auth.errors.tracing import add_trace + +__all__ = ["http_4xx_error_handlers"] + +logger = logging.getLogger(__name__) + +def page_not_found(exc): + """404 handler.""" + logger.error("Page '%s' was not found.", request.url, exc_info=True) + content_type = request.content_type + if bool(content_type) and content_type.lower() == "application/json": + return jsonify(add_trace(exc, { + "error": exc.name, + "error_description": (f"The page '{request.url}' does not exist on " + "this server.") + })), exc.code + + return render_template("404.html", page=request.url), exc.code + + +def http_4xx_error_handlers() -> dict: + """Return handlers for HTTP errors in the 400-499 range""" + return { + NotFound: page_not_found + } diff --git a/gn_auth/errors/http/http_5xx_errors.py b/gn_auth/errors/http/http_5xx_errors.py new file mode 100644 index 0000000..71d09d8 --- /dev/null +++ b/gn_auth/errors/http/http_5xx_errors.py @@ -0,0 +1,7 @@ +"""Handlers for HTTP 5** errors.""" + +__all__ = ["http_5xx_error_handlers"] + +def http_5xx_error_handlers() -> dict: + """Return handlers for HTTP errors in the 500-599 range""" + return {} diff --git a/gn_auth/errors/tracing.py b/gn_auth/errors/tracing.py new file mode 100644 index 0000000..25b544f --- /dev/null +++ b/gn_auth/errors/tracing.py @@ -0,0 +1,18 @@ +"""Utilities for improving error tracing.""" +import logging +import traceback + +from flask import request + +logger = logging.getLogger(__name__) + + +def add_trace(exc: Exception, errobj: dict) -> dict: + """Add the traceback to the error handling object.""" + logger.error("Endpoint: %s\n%s", + request.url, + traceback.format_exception(exc)) + return { + **errobj, + "error-trace": "".join(traceback.format_exception(exc)) + } |