From 0231fa869edacb05f84b1d914ad981b1e70cbd55 Mon Sep 17 00:00:00 2001 From: syeopite <70992037+syeopite@users.noreply.github.com> Date: Mon, 17 Jun 2024 18:44:25 +0000 Subject: [PATCH] Add basic fallback error handler (#46) This commit adds a proper basic fallback error handler that shows debeug information and the context of when the error has occured. This replaces the default Sanic error handler which does not show any debug information when development mode is off. The styling for the error handler is very basic and serves as a placeholder until a proper design can be done for it. This will likely be a v0.3.0 feature rather than v0.1.0 one. --- locales/en_US/LC_MESSAGES/priviblur.po | 18 +++++ src/exceptions/error_handlers/_base.py | 34 ++++++++ .../error_handlers/miscellaneous_errors.py | 17 ++++ src/server.py | 5 +- src/templates/misc/generic_error.jinja | 80 +++++++++++++++++++ 5 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/templates/misc/generic_error.jinja diff --git a/locales/en_US/LC_MESSAGES/priviblur.po b/locales/en_US/LC_MESSAGES/priviblur.po index 713d379..87a88fb 100644 --- a/locales/en_US/LC_MESSAGES/priviblur.po +++ b/locales/en_US/LC_MESSAGES/priviblur.po @@ -133,6 +133,24 @@ msgstr "Priviblur was unable to complete the request to Tumblr before timing out msgid "priviblur_error_invalid_internal_tumblr_redirect" msgstr "Error: Tumblr HTTP 301 redirect points to foreign URL" +msgid "priviblur_error_generic" +msgstr "An unknown exception has occured!" + +msgid "priviblur_error_generic_description" +msgstr "It looks like you have found a bug in Priviblur." + +msgid "priviblur_error_generic_description_2" +msgstr "Please report it here at GitHub" + +msgid "priviblur_error_generic_technical_details_error_name" +msgstr "Error: {0}" + +msgid "priviblur_error_generic_technical_details_error_message" +msgstr "Message: {0}" + +msgid "priviblur_error_generic_technical_details_error_context" +msgstr "Context:" + msgid "post_community_label_mature_heading" msgstr "Community Label: Mature" diff --git a/src/exceptions/error_handlers/_base.py b/src/exceptions/error_handlers/_base.py index 8b8be11..078449b 100644 --- a/src/exceptions/error_handlers/_base.py +++ b/src/exceptions/error_handlers/_base.py @@ -1,3 +1,5 @@ +import inspect + class ErrorHandlerGroup: """Manages and registers error handler functions for specific exceptions @@ -24,3 +26,35 @@ def register_handlers_into_app(self, app): for handler, exceptions in self.registered_handlers.items(): for exception in exceptions: app.error_handler.add(exception, handler) + + +def create_user_friendly_error_message(request, exception): + # Taken from https://github.com/searxng/searxng/blob/f5eb56b63f250c7804e5e1cf4426e550bc933906/searx/metrics/error_recorder.py + exception_class = exception.__class__ + exception_name = exception_class.__qualname__ + exception_module = exception_class.__module__ + + if exception_module is None or exception_module == str.__class__.__module__: + processed_exception_name = exception_name + else: + processed_exception_name = f"{exception_module}.{exception_name}" + + exception_message = str(exception) or None + + frame = inspect.trace() + context = [] + + for trace in reversed(frame): + if trace.filename.startswith(request.app.ctx.PRIVIBLUR_PARENT_DIR_PATH): + local_path = trace.filename[len(request.app.ctx.PRIVIBLUR_PARENT_DIR_PATH) + 1:] + else: + local_path = trace.filename + occurrence = f"File \"{local_path}\" line {trace.lineno}: in {trace.function}" + + # Add code context is applicable + if trace.code_context: + occurrence = f"{occurrence}\n {trace.code_context[0].strip()}" + + context.append(occurrence) + + return processed_exception_name, exception_message, '\n'.join(context) \ No newline at end of file diff --git a/src/exceptions/error_handlers/miscellaneous_errors.py b/src/exceptions/error_handlers/miscellaneous_errors.py index dda1aac..f017421 100644 --- a/src/exceptions/error_handlers/miscellaneous_errors.py +++ b/src/exceptions/error_handlers/miscellaneous_errors.py @@ -49,3 +49,20 @@ async def invalid_redirect(request, exception): }, status=502 ) + + +@miscellaneous_errors.register(Exception) +async def generic_error(request, exception): + name, message, context = _base.create_user_friendly_error_message(request, exception) + + return await sanic_ext.render( + "misc/generic_error.jinja", + context={ + "app": request.app, + "exception": exception, + "exception_name": name, + "exception_message": message, + "exception_context": context, + }, + status=500 + ) diff --git a/src/server.py b/src/server.py index 18a3a2d..d43e1c7 100644 --- a/src/server.py +++ b/src/server.py @@ -1,9 +1,7 @@ import os -import asyncio import logging import urllib.parse import functools -import copy import sanic import aiohttp @@ -61,6 +59,9 @@ app.ctx.PRIVIBLUR_CONFIG = config app.ctx.translate = i18n.translate +app.ctx.PRIVIBLUR_PARENT_DIR_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + + @app.listener("before_server_start") async def initialize(app): priviblur_backend = app.ctx.PRIVIBLUR_CONFIG.backend diff --git a/src/templates/misc/generic_error.jinja b/src/templates/misc/generic_error.jinja new file mode 100644 index 0000000..dc3870d --- /dev/null +++ b/src/templates/misc/generic_error.jinja @@ -0,0 +1,80 @@ +{# Displays information about some generic exception to the user #} + +{% extends "base.jinja" %} +{% block head %} + + +{% endblock %} +{% block title %}Error{% endblock %} + +{% block center %} +
+
+
+

{{translate(request.ctx.language, "priviblur_error_generic")}}

+

{{translate(request.ctx.language, "priviblur_error_generic_description")}}

+ {{translate(request.ctx.language, "priviblur_error_generic_description_2")}} +
+ +
+
+ Technical details +
{{translate(request.ctx.language, "priviblur_error_generic_technical_details_error_name", substitution=exception_name)}}
+ {% if exception_message %}
{{translate(request.ctx.language, "priviblur_error_generic_technical_details_error_message", substitution='"' + exception_message + '"')}}
{% endif %} +
{{-translate(request.ctx.language, "priviblur_error_generic_technical_details_error_context")}}
+
{{exception_context}}
+
+
+ +
+
+{%- endblock %}