From ec7ef7ba779e4863ec7f38be8d3e2125d3ff7cf0 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 15 Sep 2016 15:17:21 +0100 Subject: [PATCH] Include all WSGI-mandated headers in Page.dummy_request As specified by https://www.python.org/dev/peps/pep-3333/#environ-variables . Fixes #2989 --- wagtail/wagtailcore/models.py | 24 ++++++++++------ wagtail/wagtailcore/tests/test_page_model.py | 30 ++++++++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index a01de5c44..332f13ed3 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -1192,6 +1192,7 @@ class Page(six.with_metaclass(PageBase, AbstractPage, index.Indexed, Clusterable hostname = url_info.hostname path = url_info.path port = url_info.port or 80 + scheme = url_info.scheme else: # Cannot determine a URL to this page - cobble one together based on # whatever we find in ALLOWED_HOSTS @@ -1205,26 +1206,33 @@ class Page(six.with_metaclass(PageBase, AbstractPage, index.Indexed, Clusterable hostname = 'localhost' path = '/' port = 80 + scheme = 'http' dummy_values = { 'REQUEST_METHOD': 'GET', 'PATH_INFO': path, 'SERVER_NAME': hostname, 'SERVER_PORT': port, + 'SERVER_PROTOCOL': 'HTTP/1.1', 'HTTP_HOST': hostname, + 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), + 'wsgi.errors': StringIO(), + 'wsgi.url_scheme': scheme, + 'wsgi.multithread': True, + 'wsgi.multiprocess': True, + 'wsgi.run_once': False, } # Add important values from the original request object, if it was provided. + HEADERS_FROM_ORIGINAL_REQUEST = [ + 'REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'HTTP_COOKIE', 'HTTP_USER_AGENT', + 'wsgi.version', 'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.run_once', + ] if original_request: - if original_request.META.get('REMOTE_ADDR'): - dummy_values['REMOTE_ADDR'] = original_request.META['REMOTE_ADDR'] - if original_request.META.get('HTTP_X_FORWARDED_FOR'): - dummy_values['HTTP_X_FORWARDED_FOR'] = original_request.META['HTTP_X_FORWARDED_FOR'] - if original_request.META.get('HTTP_COOKIE'): - dummy_values['HTTP_COOKIE'] = original_request.META['HTTP_COOKIE'] - if original_request.META.get('HTTP_USER_AGENT'): - dummy_values['HTTP_USER_AGENT'] = original_request.META['HTTP_USER_AGENT'] + for header in HEADERS_FROM_ORIGINAL_REQUEST: + if header in original_request.META: + dummy_values[header] = original_request.META[header] # Add additional custom metadata sent by the caller. dummy_values.update(**meta) diff --git a/wagtail/wagtailcore/tests/test_page_model.py b/wagtail/wagtailcore/tests/test_page_model.py index 5381595fc..7b3492c65 100644 --- a/wagtail/wagtailcore/tests/test_page_model.py +++ b/wagtail/wagtailcore/tests/test_page_model.py @@ -1160,6 +1160,21 @@ class TestDummyRequest(TestCase): self.assertEqual(request.path, '/events/') self.assertEqual(request.META['HTTP_HOST'], 'localhost') + # check other env vars required by the WSGI spec + self.assertEqual(request.META['REQUEST_METHOD'], 'GET') + self.assertEqual(request.META['SCRIPT_NAME'], '') + self.assertEqual(request.META['PATH_INFO'], '/events/') + self.assertEqual(request.META['SERVER_NAME'], 'localhost') + self.assertEqual(request.META['SERVER_PORT'], 80) + self.assertEqual(request.META['SERVER_PROTOCOL'], 'HTTP/1.1') + self.assertEqual(request.META['wsgi.version'], (1, 0)) + self.assertEqual(request.META['wsgi.url_scheme'], 'http') + self.assertIn('wsgi.input', request.META) + self.assertIn('wsgi.errors', request.META) + self.assertIn('wsgi.multithread', request.META) + self.assertIn('wsgi.multiprocess', request.META) + self.assertIn('wsgi.run_once', request.META) + def test_dummy_request_for_accessible_page_with_original_request(self): event_index = Page.objects.get(url_path='/home/events/') original_headers = { @@ -1178,6 +1193,21 @@ class TestDummyRequest(TestCase): self.assertEqual(request.META['HTTP_COOKIE'], original_request.META['HTTP_COOKIE']) self.assertEqual(request.META['HTTP_USER_AGENT'], original_request.META['HTTP_USER_AGENT']) + # check other env vars required by the WSGI spec + self.assertEqual(request.META['REQUEST_METHOD'], 'GET') + self.assertEqual(request.META['SCRIPT_NAME'], '') + self.assertEqual(request.META['PATH_INFO'], '/events/') + self.assertEqual(request.META['SERVER_NAME'], 'localhost') + self.assertEqual(request.META['SERVER_PORT'], 80) + self.assertEqual(request.META['SERVER_PROTOCOL'], 'HTTP/1.1') + self.assertEqual(request.META['wsgi.version'], (1, 0)) + self.assertEqual(request.META['wsgi.url_scheme'], 'http') + self.assertIn('wsgi.input', request.META) + self.assertIn('wsgi.errors', request.META) + self.assertIn('wsgi.multithread', request.META) + self.assertIn('wsgi.multiprocess', request.META) + self.assertIn('wsgi.run_once', request.META) + @override_settings(ALLOWED_HOSTS=['production.example.com']) def test_dummy_request_for_inaccessible_page_should_use_valid_host(self): root_page = Page.objects.get(url_path='/')