diff options
| author | Alexandre Varas <346508+alej0varas@users.noreply.github.com> | 2019-06-05 20:12:21 +0200 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-06-07 07:51:45 +0200 |
| commit | c498f088c584ec3aff97409fdc11b39b28240de9 (patch) | |
| tree | 0f156b2cbf57c7d9cadeab5bb6245b4b19fada2f | |
| parent | 3fb0a1a67f0ca3e03db59a876f87e8d0828872c4 (diff) | |
Fixed #30521 -- Fixed invalid HTML in default error pages.
| -rw-r--r-- | django/views/defaults.py | 33 | ||||
| -rw-r--r-- | 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 = """ +<!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, @@ -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( - '<h1>Not Found</h1>' - '<p>The requested resource was not found on this server.</p>') + 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('<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()) @@ -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('<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. 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('<h1>403 Forbidden</h1>', 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'<h1>Bad Request (400)</h1>') + self.assertContains(response, b'<h1>Bad Request (400)</h1>', 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'<!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) |
