From c498f088c584ec3aff97409fdc11b39b28240de9 Mon Sep 17 00:00:00 2001
From: Alexandre Varas <346508+alej0varas@users.noreply.github.com>
Date: Wed, 5 Jun 2019 20:12:21 +0200
Subject: [PATCH] Fixed #30521 -- Fixed invalid HTML in default error pages.
---
django/views/defaults.py | 33 +++++++++++++++++++++----
tests/view_tests/tests/test_defaults.py | 18 ++++++++++++--
2 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/django/views/defaults.py b/django/views/defaults.py
index 1176bdeeeb..2fb0d0b38c 100644
--- a/django/views/defaults.py
+++ b/django/views/defaults.py
@@ -11,6 +11,17 @@ ERROR_404_TEMPLATE_NAME = '404.html'
ERROR_403_TEMPLATE_NAME = '403.html'
ERROR_400_TEMPLATE_NAME = '400.html'
ERROR_500_TEMPLATE_NAME = '500.html'
+ERROR_PAGE_TEMPLATE = """
+
+
+
+ %(title)s
+
+
+ %(title)s
%(details)s
+
+
+"""
# This can be called when CsrfViewMiddleware.process_view has not run,
@@ -55,8 +66,11 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
# Render template (even though there are no substitutions) to allow
# inspecting the context in tests.
template = Engine().from_string(
- 'Not Found
'
- 'The requested resource was not found on this server.
')
+ ERROR_PAGE_TEMPLATE % {
+ 'title': 'Not Found',
+ 'details': 'The requested resource was not found on this server.',
+ },
+ )
body = template.render(Context(context))
content_type = 'text/html'
return HttpResponseNotFound(body, content_type=content_type)
@@ -76,7 +90,10 @@ def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
if template_name != ERROR_500_TEMPLATE_NAME:
# Reraise if it's a missing custom template.
raise
- return HttpResponseServerError('Server Error (500)
', content_type='text/html')
+ return HttpResponseServerError(
+ ERROR_PAGE_TEMPLATE % {'title': 'Server Error (500)', 'details': ''},
+ content_type='text/html',
+ )
return HttpResponseServerError(template.render())
@@ -94,7 +111,10 @@ def bad_request(request, exception, template_name=ERROR_400_TEMPLATE_NAME):
if template_name != ERROR_400_TEMPLATE_NAME:
# Reraise if it's a missing custom template.
raise
- return HttpResponseBadRequest('Bad Request (400)
', content_type='text/html')
+ return HttpResponseBadRequest(
+ ERROR_PAGE_TEMPLATE % {'title': 'Bad Request (400)', 'details': ''},
+ content_type='text/html',
+ )
# No exception content is passed to the template, to not disclose any sensitive information.
return HttpResponseBadRequest(template.render())
@@ -119,7 +139,10 @@ def permission_denied(request, exception, template_name=ERROR_403_TEMPLATE_NAME)
if template_name != ERROR_403_TEMPLATE_NAME:
# Reraise if it's a missing custom template.
raise
- return HttpResponseForbidden('403 Forbidden
', content_type='text/html')
+ return HttpResponseForbidden(
+ ERROR_PAGE_TEMPLATE % {'title': '403 Forbidden', 'details': ''},
+ content_type='text/html',
+ )
return HttpResponseForbidden(
template.render(request=request, context={'exception': str(exception)})
)
diff --git a/tests/view_tests/tests/test_defaults.py b/tests/view_tests/tests/test_defaults.py
index 4a7ad2f7bd..7ddb698422 100644
--- a/tests/view_tests/tests/test_defaults.py
+++ b/tests/view_tests/tests/test_defaults.py
@@ -81,8 +81,7 @@ class DefaultsTests(TestCase):
def test_bad_request(self):
request = self.request_factory.get('/')
response = bad_request(request, Exception())
- self.assertEqual(response.status_code, 400)
- self.assertEqual(response.content, b'Bad Request (400)
')
+ self.assertContains(response, b'Bad Request (400)
', status_code=400)
@override_settings(TEMPLATES=[{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
@@ -134,3 +133,18 @@ class DefaultsTests(TestCase):
with self.assertRaises(TemplateDoesNotExist):
server_error(request, template_name='nonexistent')
+
+ def test_error_pages(self):
+ request = self.request_factory.get('/')
+ for response, title in (
+ (bad_request(request, Exception()), b'Bad Request (400)'),
+ (permission_denied(request, Exception()), b'403 Forbidden'),
+ (page_not_found(request, Http404()), b'Not Found'),
+ (server_error(request), b'Server Error (500)'),
+ ):
+ with self.subTest(title=title):
+ self.assertIn(b'', response.content)
+ self.assertIn(b'', response.content)
+ self.assertIn(b'', response.content)
+ self.assertIn(b'%s' % title, response.content)
+ self.assertIn(b'', response.content)