Explorar el Código

HUE-964 [core] 500 errors should go to default debugger if we cannot render custom 500

The scenario where we do not have all the context prepared for proper rendering of a 500 error
is when there is an error early on in the middleware pipeline. IE: an import error.
abec hace 13 años
padre
commit
ab5cee9432
Se han modificado 2 ficheros con 39 adiciones y 3 borrados
  1. 28 1
      desktop/core/src/desktop/tests.py
  2. 11 2
      desktop/core/src/desktop/views.py

+ 28 - 1
desktop/core/src/desktop/tests.py

@@ -18,11 +18,12 @@
 from desktop.lib import django_mako
 
 from nose.tools import assert_true, assert_equal, assert_not_equal
-from desktop.lib.django_test_util import make_logged_in_client
 from django.conf.urls.defaults import patterns, url
 from django.core.urlresolvers import reverse
 from django.http import HttpResponse
 from django.db.models import query, CharField, SmallIntegerField
+from django.test.client import Client
+from desktop.lib.django_test_util import make_logged_in_client
 from desktop.lib.paginator import Paginator
 from desktop.lib.conf import validate_path
 import desktop
@@ -292,6 +293,32 @@ def test_error_handling():
     restore_500_debug()
 
 
+def test_error_handling_failure():
+  # Change rewrite_user to call has_hue_permission
+  # Try to get filebrowser page
+  # test for werkzeug debugger
+  # Restore rewrite_user
+
+  restore_django_debug = desktop.conf.DJANGO_DEBUG_MODE.set_for_testing(False)
+  restore_500_debug = desktop.conf.HTTP_500_DEBUG_MODE.set_for_testing(False)
+
+  # Add an error view
+  setattr(views.serve_500_error, 'login_notrequired', True)
+  error_url_pat = patterns('', url('^500_internal_error$', views.serve_500_error))
+  desktop.urls.urlpatterns.extend(error_url_pat)
+  try:
+    c = Client()
+    response = c.get('/500_internal_error')
+    assert_true('AttributeError at /500_internal_error' in response.content, response)
+  finally:
+    # Restore the world
+    for i in error_url_pat:
+      desktop.urls.urlpatterns.remove(i)
+    restore_django_debug()
+    restore_500_debug()
+    delattr(views.serve_500_error, 'login_notrequired')
+
+
 def test_404_handling():
   view_name = '/the-view-that-is-not-there'
   c = make_logged_in_client()

+ 11 - 2
desktop/core/src/desktop/views.py

@@ -221,7 +221,15 @@ def serve_500_error(request, *args, **kwargs):
   """Registered handler for 500. We use the debug view to make debugging easier."""
   if desktop.conf.HTTP_500_DEBUG_MODE.get():
     return django.views.debug.technical_500_response(request, *sys.exc_info())
-  return render("500.mako", request, {'traceback': traceback.extract_tb(sys.exc_info()[2])})
+  try:
+    return render("500.mako", request, {'traceback': traceback.extract_tb(sys.exc_info()[2])})
+  except:
+    # Fallback to technical 500 response if ours fails
+    # Will end up here:
+    #   - Middleware or authentication backends problems
+    #   - Certain missing imports
+    #   - Packaging and install issues
+    return django.views.debug.technical_500_response(request, *sys.exc_info())
 
 _LOG_LEVELS = {
   "critical": logging.CRITICAL,
@@ -270,7 +278,8 @@ def commonheader(title, section, user, padding="60px"):
   """
   Returns the rendered common header
   """
-  apps_list = sorted(appmanager.get_apps(user), key=lambda app: app.menu_index)
+  apps = appmanager.get_apps(user)
+  apps_list = sorted(apps, key=lambda app: app.menu_index)
 
   return django_mako.render_to_string("common_header.mako", dict(
     apps=apps_list,