From e60557c249d33e100008cc30890cde2daeb677bb Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 28 Jan 2015 12:03:05 -0500 Subject: [PATCH] [1.4.x] Fixed #24238 -- Removed unused WSGIRequestHandler.get_environ() Also moved the test as it wasn't running. --- django/core/servers/basehttp.py | 33 --------- .../servers/servers/test_basehttp.py | 67 ------------------- tests/regressiontests/servers/tests.py | 67 ++++++++++++++++++- 3 files changed, 66 insertions(+), 101 deletions(-) delete mode 100644 tests/regressiontests/servers/servers/test_basehttp.py diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 0ec5f98cb8..d570657cd5 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -138,39 +138,6 @@ class WSGIRequestHandler(simple_server.WSGIRequestHandler, object): self.style = color_style() super(WSGIRequestHandler, self).__init__(*args, **kwargs) - def get_environ(self): - env = self.server.base_environ.copy() - env['SERVER_PROTOCOL'] = self.request_version - env['REQUEST_METHOD'] = self.command - if '?' in self.path: - path,query = self.path.split('?',1) - else: - path,query = self.path,'' - - env['PATH_INFO'] = urllib.unquote(path) - env['QUERY_STRING'] = query - env['REMOTE_ADDR'] = self.client_address[0] - - if self.headers.typeheader is None: - env['CONTENT_TYPE'] = self.headers.type - else: - env['CONTENT_TYPE'] = self.headers.typeheader - - length = self.headers.getheader('content-length') - if length: - env['CONTENT_LENGTH'] = length - - for h in self.headers.headers: - k,v = h.split(':',1) - k=k.replace('-','_').upper(); v=v.strip() - if k in env: - continue # skip content length, type,etc. - if 'HTTP_'+k in env: - env['HTTP_'+k] += ','+v # comma-separate multiple headers - else: - env['HTTP_'+k] = v - return env - def log_message(self, format, *args): # Don't bother logging requests for admin images or the favicon. if (self.path.startswith(self.admin_media_prefix) diff --git a/tests/regressiontests/servers/servers/test_basehttp.py b/tests/regressiontests/servers/servers/test_basehttp.py deleted file mode 100644 index 6bca608d17..0000000000 --- a/tests/regressiontests/servers/servers/test_basehttp.py +++ /dev/null @@ -1,67 +0,0 @@ -import sys - -from django.core.servers.basehttp import WSGIRequestHandler -from django.test import TestCase -from django.utils.six import BytesIO, StringIO - - -class Stub(object): - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - -class WSGIRequestHandlerTestCase(TestCase): - - def test_strips_underscore_headers(self): - """WSGIRequestHandler ignores headers containing underscores. - - This follows the lead of nginx and Apache 2.4, and is to avoid - ambiguity between dashes and underscores in mapping to WSGI environ, - which can have security implications. - """ - def test_app(environ, start_response): - """A WSGI app that just reflects its HTTP environ.""" - start_response('200 OK', []) - http_environ_items = sorted( - '%s:%s' % (k, v) for k, v in environ.items() - if k.startswith('HTTP_') - ) - yield (','.join(http_environ_items)).encode('utf-8') - - rfile = BytesIO() - rfile.write(b"GET / HTTP/1.0\r\n") - rfile.write(b"Some-Header: good\r\n") - rfile.write(b"Some_Header: bad\r\n") - rfile.write(b"Other_Header: bad\r\n") - rfile.seek(0) - - # WSGIRequestHandler closes the output file; we need to make this a - # no-op so we can still read its contents. - class UnclosableBytesIO(BytesIO): - def close(self): - pass - - wfile = UnclosableBytesIO() - - def makefile(mode, *a, **kw): - if mode == 'rb': - return rfile - elif mode == 'wb': - return wfile - - request = Stub(makefile=makefile) - server = Stub(base_environ={}, get_app=lambda: test_app) - - # We don't need to check stderr, but we don't want it in test output - old_stderr = sys.stderr - sys.stderr = StringIO() - try: - # instantiating a handler runs the request as side effect - WSGIRequestHandler(request, '192.168.0.2', server) - finally: - sys.stderr = old_stderr - - wfile.seek(0) - body = list(wfile.readlines())[-1] - - self.assertEqual(body, b'HTTP_SOME_HEADER:good') diff --git a/tests/regressiontests/servers/tests.py b/tests/regressiontests/servers/tests.py index d237c83c65..e0a66f675f 100644 --- a/tests/regressiontests/servers/tests.py +++ b/tests/regressiontests/servers/tests.py @@ -2,6 +2,7 @@ Tests for django.core.servers. """ import os +import sys from urlparse import urljoin import urllib2 @@ -10,8 +11,10 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.test import TestCase, LiveServerTestCase from django.core.handlers.wsgi import WSGIHandler -from django.core.servers.basehttp import AdminMediaHandler, WSGIServerException +from django.core.servers.basehttp import ( + AdminMediaHandler, WSGIRequestHandler, WSGIServerException) from django.test.utils import override_settings +from django.utils.six import BytesIO, StringIO from .models import Person @@ -213,3 +216,65 @@ class LiveServerDatabase(LiveServerBase): self.urlopen('/create_model_instance/') names = [person.name for person in Person.objects.all()] self.assertEquals(names, ['jane', 'robert', 'emily']) + + +class Stub(object): + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +class WSGIRequestHandlerTestCase(TestCase): + + def test_strips_underscore_headers(self): + """WSGIRequestHandler ignores headers containing underscores. + + This follows the lead of nginx and Apache 2.4, and is to avoid + ambiguity between dashes and underscores in mapping to WSGI environ, + which can have security implications. + """ + def test_app(environ, start_response): + """A WSGI app that just reflects its HTTP environ.""" + start_response('200 OK', []) + http_environ_items = sorted( + '%s:%s' % (k, v) for k, v in environ.items() + if k.startswith('HTTP_') + ) + yield (','.join(http_environ_items)).encode('utf-8') + + rfile = BytesIO() + rfile.write("GET / HTTP/1.0\r\n") + rfile.write("Some-Header: good\r\n") + rfile.write("Some_Header: bad\r\n") + rfile.write("Other_Header: bad\r\n") + rfile.seek(0) + + # WSGIRequestHandler closes the output file; we need to make this a + # no-op so we can still read its contents. + class UnclosableBytesIO(BytesIO): + def close(self): + pass + + wfile = UnclosableBytesIO() + + def makefile(mode, *a, **kw): + if mode == 'rb': + return rfile + elif mode == 'wb': + return wfile + + request = Stub(makefile=makefile) + server = Stub(base_environ={}, get_app=lambda: test_app) + + # We don't need to check stderr, but we don't want it in test output + old_stderr = sys.stderr + sys.stderr = StringIO() + try: + # instantiating a handler runs the request as side effect + WSGIRequestHandler(request, '192.168.0.2', server) + finally: + sys.stderr = old_stderr + + wfile.seek(0) + body = list(wfile.readlines())[-1] + + self.assertEqual(body, 'HTTP_SOME_HEADER:good')