瀏覽代碼

HUE-51. Hue needs a 500 template

bc Wong 15 年之前
父節點
當前提交
59dd976926

+ 3 - 0
desktop/conf.dist/hue.ini

@@ -30,6 +30,9 @@ time_zone=America/Los_Angeles
 # Turn off debug
 django_debug_mode=0
 
+# Turn off backtrace for server error
+http_500_debug_mode=0
+
 # Webserver runs as this user
 ## server_user=hue
 ## server_group=hue

+ 9 - 0
desktop/core/src/desktop/conf.py

@@ -238,3 +238,12 @@ DJANGO_DEBUG_MODE = Config(
   type=coerce_bool,
   default=True
 )
+
+HTTP_500_DEBUG_MODE = Config(
+  key='http_500_debug_mode',
+  help='Enable or disable debugging information in the 500 internal server error response. '
+       'Note that the debugging information may contain sensitive data. '
+       'If django_debug_mode is True, this is automatically enabled.',
+  type=coerce_bool,
+  default=True
+)

+ 32 - 0
desktop/core/src/desktop/templates/404.html

@@ -0,0 +1,32 @@
+{% comment %}
+Licensed to Cloudera, Inc. under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  Cloudera, Inc. licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Page Not Found</title>
+</head>
+<body>
+
+<h2>Page Not Found</h2>
+
+<p>We're sorry, but the requested page could not be found:
+<br/>
+{{uri}}
+</p>
+
+</body>
+</html>

+ 28 - 0
desktop/core/src/desktop/templates/500.html

@@ -0,0 +1,28 @@
+{% comment %}
+Licensed to Cloudera, Inc. under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  Cloudera, Inc. licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Internal Server Error</title>
+</head>
+<body>
+  <h2>Server Error (500)</h2>
+  <p>There's been an error. It's been reported to the site administrators
+  via e-mail and should be fixed shortly. Thanks for your patience.</p>
+  <a href="/">Home</a>
+</body>
+</html>

+ 45 - 0
desktop/core/src/desktop/tests.py

@@ -18,6 +18,7 @@ from desktop.lib import django_mako
 
 from nose.tools import assert_true, assert_equal
 from desktop.lib.django_test_util import make_logged_in_client
+from django.conf.urls.defaults import patterns, url
 from django.http import HttpResponse
 from django.db.models import query, CharField, SmallIntegerField
 from desktop.lib.paginator import Paginator
@@ -194,3 +195,47 @@ def test_truncating_model():
 
   a.non_string_field = 10**10
   assert_true(a.non_string_field == 10**10, 'non-string fields are not truncated')
+
+
+def test_500_handling():
+  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)
+
+  exc_msg = "error_raising_view: Test 500 handling"
+  def error_raising_view(request, *args, **kwargs):
+    raise Exception(exc_msg)
+
+  # Add an error view
+  error_url_pat = patterns('', url('^500_internal_error$', error_raising_view))[0]
+  desktop.urls.urlpatterns.append(error_url_pat)
+  try:
+    def store_exc_info(*args, **kwargs):
+      pass
+    # Disable the test client's exception forwarding
+    c = make_logged_in_client()
+    c.store_exc_info = store_exc_info
+
+    response = c.get('/500_internal_error')
+    assert_equal(response.template.name, '500.html')
+    assert_true('should be fixed shortly. Thanks for your patience' in response.content)
+    assert_true(exc_msg not in response.content)
+
+    # Now test the 500 handler with backtrace
+    desktop.conf.HTTP_500_DEBUG_MODE.set_for_testing(True)
+    response = c.get('/500_internal_error')
+    assert_equal(response.template.name, 'Technical 500 template')
+    assert_true(exc_msg in response.content)
+  finally:
+    # Restore the world
+    desktop.urls.urlpatterns.remove(error_url_pat)
+    restore_django_debug()
+    restore_500_debug()
+
+
+def test_404_handling():
+  view_name = '/the-view-that-is-not-there'
+  c = make_logged_in_client()
+  response = c.get(view_name)
+  assert_equal(response.template.name, '404.html')
+  assert_true('Page Not Found' in response.content)
+  assert_true(view_name in response.content)

+ 9 - 4
desktop/core/src/desktop/urls.py

@@ -19,14 +19,19 @@ import logging
 import os
 import re
 
-# The "*" import below is important.  
-# Django expects, for example, handler500 and handler404
-# to be defined.  See http://code.djangoproject.com/ticket/5350
-from django.conf.urls.defaults import *
+from django.conf.urls.defaults import include, patterns, url
 from django.contrib import admin
+
 from desktop import appmanager
 import depender.urls
 
+# Django expects handler404 and handler500 to be defined.
+# django.conf.urls.defaults provides them. But we want to override them.
+# Also see http://code.djangoproject.com/ticket/5350
+handler404 = 'desktop.views.serve_404_error'
+handler500 = 'desktop.views.serve_500_error'
+
+
 # Set up /appname/static mappings for any apps that have static directories
 def static_pattern(urlprefix, root):
   """

+ 18 - 3
desktop/core/src/desktop/views.py

@@ -16,20 +16,22 @@
 # limitations under the License.
 
 import logging
-import zipfile
+import sys
 import tempfile
 import time
-import sys
 import traceback
+import zipfile
 
 from django.shortcuts import render_to_response
 from django.http import HttpResponse
 from django.core.servers.basehttp import FileWrapper
+import django.views.debug
 
 from desktop.lib.django_util import login_notrequired, render_json, render
-from desktop.log.access import access_log_level
+from desktop.log.access import access_log_level, access_warn
 from desktop.models import UserPreferences
 from desktop import appmanager
+import desktop.conf
 import desktop.log.log_buffer
 
 LOG = logging.getLogger(__name__)
@@ -196,3 +198,16 @@ def index(request):
   return render("index.mako", request, dict(
     feedback_url=desktop.conf.FEEDBACK_URL.get()
   ))
+
+def serve_404_error(request, *args, **kwargs):
+  """Registered handler for 404. We just return a simple error"""
+  access_warn(request, "404 not found")
+  return render_to_response("404.html", dict(uri=request.build_absolute_uri()))
+  return HttpResponse('Page not found. You are trying to access %s' % (request.build_absolute_uri(),),
+                      content_type="text/plain")
+
+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_to_response("500.html")