Просмотр исходного кода

Fixes #2266: Permit additional logging of exceptions beyond custom middleware

Jeremy Stretch 7 лет назад
Родитель
Сommit
c8a73b5b15
3 измененных файлов с 41 добавлено и 16 удалено
  1. 2 0
      netbox/netbox/urls.py
  2. 16 15
      netbox/utilities/middleware.py
  3. 23 1
      netbox/utilities/views.py

+ 2 - 0
netbox/netbox/urls.py

@@ -74,3 +74,5 @@ if settings.DEBUG:
 urlpatterns = [
     url(r'^{}'.format(settings.BASE_PATH), include(_patterns))
 ]
+
+handler500 = 'utilities.views.server_error'

+ 16 - 15
netbox/utilities/middleware.py

@@ -4,8 +4,8 @@ import sys
 
 from django.conf import settings
 from django.db import ProgrammingError
-from django.http import Http404, HttpResponseRedirect
-from django.shortcuts import render
+from django.http import Http404, HttpResponseRedirect, HttpResponseServerError
+from django.template import loader
 from django.urls import reverse
 
 BASE_PATH = getattr(settings, 'BASE_PATH', False)
@@ -65,23 +65,24 @@ class ExceptionHandlingMiddleware(object):
         if isinstance(exception, Http404):
             return
 
-        # Determine the type of exception
+        # Determine the type of exception. If it's a common issue, return a custom error page with instructions.
+        custom_template = None
         if isinstance(exception, ProgrammingError):
-            template_name = 'exceptions/programming_error.html'
+            custom_template = 'exceptions/programming_error.html'
         elif isinstance(exception, ImportError):
-            template_name = 'exceptions/import_error.html'
+            custom_template = 'exceptions/import_error.html'
         elif (
             sys.version_info[0] >= 3 and isinstance(exception, PermissionError)
         ) or (
             isinstance(exception, OSError) and exception.errno == 13
         ):
-            template_name = 'exceptions/permission_error.html'
-        else:
-            template_name = '500.html'
-
-        # Return an error message
-        type_, error, traceback = sys.exc_info()
-        return render(request, template_name, {
-            'exception': str(type_),
-            'error': error,
-        }, status=500)
+            custom_template = 'exceptions/permission_error.html'
+
+        # Return a custom error message, or fall back to Django's default 500 error handling (500.html)
+        if custom_template:
+            type_, error, traceback = sys.exc_info()
+            template = loader.get_template(custom_template)
+            return HttpResponseServerError(template.render({
+                'exception': str(type_),
+                'error': error,
+            }))

+ 23 - 1
netbox/utilities/views.py

@@ -2,6 +2,7 @@ from __future__ import unicode_literals
 
 from collections import OrderedDict
 from copy import deepcopy
+import sys
 
 from django.conf import settings
 from django.contrib import messages
@@ -10,12 +11,16 @@ from django.core.exceptions import ValidationError
 from django.db import transaction, IntegrityError
 from django.db.models import ProtectedError
 from django.forms import CharField, Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea
+from django.http import HttpResponseServerError
 from django.shortcuts import get_object_or_404, redirect, render
-from django.template.exceptions import TemplateSyntaxError
+from django.template import loader
+from django.template.exceptions import TemplateDoesNotExist, TemplateSyntaxError
 from django.urls import reverse
 from django.utils.html import escape
 from django.utils.http import is_safe_url
 from django.utils.safestring import mark_safe
+from django.views.decorators.csrf import requires_csrf_token
+from django.views.defaults import ERROR_500_TEMPLATE_NAME
 from django.views.generic import View
 from django_tables2 import RequestConfig
 
@@ -858,3 +863,20 @@ class BulkComponentCreateView(View):
             'table': table,
             'return_url': reverse(self.default_return_url),
         })
+
+
+@requires_csrf_token
+def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
+    """
+    Custom 500 handler to provide additional context when rendering 500.html.
+    """
+    try:
+        template = loader.get_template(template_name)
+    except TemplateDoesNotExist:
+        return HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
+    type_, error, traceback = sys.exc_info()
+
+    return HttpResponseServerError(template.render({
+        'exception': str(type_),
+        'error': error,
+    }))