mirror of https://github.com/django/django.git
Fixed #30521 -- Fixed invalid HTML in default error pages.
This commit is contained in:
parent
3fb0a1a67f
commit
c498f088c5
|
@ -11,6 +11,17 @@ ERROR_404_TEMPLATE_NAME = '404.html'
|
||||||
ERROR_403_TEMPLATE_NAME = '403.html'
|
ERROR_403_TEMPLATE_NAME = '403.html'
|
||||||
ERROR_400_TEMPLATE_NAME = '400.html'
|
ERROR_400_TEMPLATE_NAME = '400.html'
|
||||||
ERROR_500_TEMPLATE_NAME = '500.html'
|
ERROR_500_TEMPLATE_NAME = '500.html'
|
||||||
|
ERROR_PAGE_TEMPLATE = """
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>%(title)s</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>%(title)s</h1><p>%(details)s</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# This can be called when CsrfViewMiddleware.process_view has not run,
|
# 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
|
# Render template (even though there are no substitutions) to allow
|
||||||
# inspecting the context in tests.
|
# inspecting the context in tests.
|
||||||
template = Engine().from_string(
|
template = Engine().from_string(
|
||||||
'<h1>Not Found</h1>'
|
ERROR_PAGE_TEMPLATE % {
|
||||||
'<p>The requested resource was not found on this server.</p>')
|
'title': 'Not Found',
|
||||||
|
'details': 'The requested resource was not found on this server.',
|
||||||
|
},
|
||||||
|
)
|
||||||
body = template.render(Context(context))
|
body = template.render(Context(context))
|
||||||
content_type = 'text/html'
|
content_type = 'text/html'
|
||||||
return HttpResponseNotFound(body, content_type=content_type)
|
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:
|
if template_name != ERROR_500_TEMPLATE_NAME:
|
||||||
# Reraise if it's a missing custom template.
|
# Reraise if it's a missing custom template.
|
||||||
raise
|
raise
|
||||||
return HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
|
return HttpResponseServerError(
|
||||||
|
ERROR_PAGE_TEMPLATE % {'title': 'Server Error (500)', 'details': ''},
|
||||||
|
content_type='text/html',
|
||||||
|
)
|
||||||
return HttpResponseServerError(template.render())
|
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:
|
if template_name != ERROR_400_TEMPLATE_NAME:
|
||||||
# Reraise if it's a missing custom template.
|
# Reraise if it's a missing custom template.
|
||||||
raise
|
raise
|
||||||
return HttpResponseBadRequest('<h1>Bad Request (400)</h1>', 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.
|
# No exception content is passed to the template, to not disclose any sensitive information.
|
||||||
return HttpResponseBadRequest(template.render())
|
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:
|
if template_name != ERROR_403_TEMPLATE_NAME:
|
||||||
# Reraise if it's a missing custom template.
|
# Reraise if it's a missing custom template.
|
||||||
raise
|
raise
|
||||||
return HttpResponseForbidden('<h1>403 Forbidden</h1>', content_type='text/html')
|
return HttpResponseForbidden(
|
||||||
|
ERROR_PAGE_TEMPLATE % {'title': '403 Forbidden', 'details': ''},
|
||||||
|
content_type='text/html',
|
||||||
|
)
|
||||||
return HttpResponseForbidden(
|
return HttpResponseForbidden(
|
||||||
template.render(request=request, context={'exception': str(exception)})
|
template.render(request=request, context={'exception': str(exception)})
|
||||||
)
|
)
|
||||||
|
|
|
@ -81,8 +81,7 @@ class DefaultsTests(TestCase):
|
||||||
def test_bad_request(self):
|
def test_bad_request(self):
|
||||||
request = self.request_factory.get('/')
|
request = self.request_factory.get('/')
|
||||||
response = bad_request(request, Exception())
|
response = bad_request(request, Exception())
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertContains(response, b'<h1>Bad Request (400)</h1>', status_code=400)
|
||||||
self.assertEqual(response.content, b'<h1>Bad Request (400)</h1>')
|
|
||||||
|
|
||||||
@override_settings(TEMPLATES=[{
|
@override_settings(TEMPLATES=[{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
@ -134,3 +133,18 @@ class DefaultsTests(TestCase):
|
||||||
|
|
||||||
with self.assertRaises(TemplateDoesNotExist):
|
with self.assertRaises(TemplateDoesNotExist):
|
||||||
server_error(request, template_name='nonexistent')
|
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'<!doctype html>', response.content)
|
||||||
|
self.assertIn(b'<html lang="en">', response.content)
|
||||||
|
self.assertIn(b'<head>', response.content)
|
||||||
|
self.assertIn(b'<title>%s</title>' % title, response.content)
|
||||||
|
self.assertIn(b'<body>', response.content)
|
||||||
|
|
Loading…
Reference in New Issue