about summary refs log tree commit diff
path: root/gn_auth/errors/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'gn_auth/errors/common.py')
-rw-r--r--gn_auth/errors/common.py58
1 files changed, 58 insertions, 0 deletions
diff --git a/gn_auth/errors/common.py b/gn_auth/errors/common.py
new file mode 100644
index 0000000..8dc0373
--- /dev/null
+++ b/gn_auth/errors/common.py
@@ -0,0 +1,58 @@
+"""Common utilities."""
+import logging
+import traceback
+from typing import Callable
+
+from flask import request, Response, make_response, render_template
+
+logger = logging.getLogger(__name__)
+
+
+def add_trace(exc: Exception, errobj: dict) -> dict:
+    """Add the traceback to the error handling object."""
+    return {
+        **errobj,
+        "error-trace": "".join(traceback.format_exception(exc))
+    }
+
+def __status_code__(exc: Exception):
+    """Fetch the error code for exceptions that have them."""
+    error_code_attributes = (
+        "code", "error_code", "errorcode", "status_code", "status_code")
+    for attr in error_code_attributes:
+        if hasattr(exc, attr):
+            return getattr(exc, attr)
+
+    return 500
+
+
+def build_handler(description: str) -> Callable[[Exception], Response]:
+    """Generic utility to build error handlers."""
+    def __handler__(exc: Exception) -> Response:
+        """Handle the exception as appropriate for requests of different mimetypes."""
+        error = (exc.name if hasattr(exc, "name") else exc.__class__.__name__)
+        status_code = __status_code__(exc)
+        content_type = request.content_type
+        if bool(content_type) and content_type.lower() == "application/json":
+            return make_response((
+                add_trace(
+                    exc,
+                    {
+                        "requested-uri": request.url,
+                        "error": error,
+                        "error_description": description
+                    }),
+                status_code,
+                {"Content-Type": "application/json"}))
+
+        return make_response((
+            render_template(
+                f"http-error-{str(status_code)[0:-2]}xx.html",
+                error=exc,
+                page=request.url,
+                description=description,
+                trace=traceback.format_exception(exc)),
+            status_code,
+            {"Content-Type": "text/html"}))
+
+    return __handler__