From bfdb7d26aa534578dbac3c43e76d8ac3a5ad6a06 Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Thu, 7 May 2009 15:39:06 +0000 Subject: [PATCH] Fixed #9659: fixed `wsgi.file_wrapper` in the builtin server. Thanks, mitsuhiko. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10690 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/servers/basehttp.py | 15 +++--- .../builtin_server/__init__.py | 0 .../regressiontests/builtin_server/models.py | 0 tests/regressiontests/builtin_server/tests.py | 51 +++++++++++++++++++ 4 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 tests/regressiontests/builtin_server/__init__.py create mode 100644 tests/regressiontests/builtin_server/models.py create mode 100644 tests/regressiontests/builtin_server/tests.py diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 287143b794..6fed0acc59 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -306,14 +306,15 @@ class ServerHandler(object): env.setdefault('SERVER_SOFTWARE',self.server_software) def finish_response(self): - """Send any iterable data, then close self and the iterable - - Subclasses intended for use in asynchronous servers will - want to redefine this method, such that it sets up callbacks - in the event loop to iterate over the data, and to call - 'self.close()' once the response is finished. """ - if not self.result_is_file() and not self.sendfile(): + Send any iterable data, then close self and the iterable + + Subclasses intended for use in asynchronous servers will want to + redefine this method, such that it sets up callbacks in the event loop + to iterate over the data, and to call 'self.close()' once the response + is finished. + """ + if not self.result_is_file() or not self.sendfile(): for data in self.result: self.write(data) self.finish_content() diff --git a/tests/regressiontests/builtin_server/__init__.py b/tests/regressiontests/builtin_server/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regressiontests/builtin_server/models.py b/tests/regressiontests/builtin_server/models.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regressiontests/builtin_server/tests.py b/tests/regressiontests/builtin_server/tests.py new file mode 100644 index 0000000000..ad3abc9e9f --- /dev/null +++ b/tests/regressiontests/builtin_server/tests.py @@ -0,0 +1,51 @@ +from unittest import TestCase +from StringIO import StringIO +from django.core.servers.basehttp import ServerHandler + +# +# Tests for #9659: wsgi.file_wrapper in the builtin server. +# We need to mock a couple of of handlers and keep track of what +# gets called when using a couple kinds of WSGI apps. +# + +class DummyHandler(object): + def log_request(*args, **kwargs): + pass + +class FileWrapperHandler(ServerHandler): + def __init__(self, *args, **kwargs): + ServerHandler.__init__(self, *args, **kwargs) + self.request_handler = DummyHandler() + self._used_sendfile = False + + def sendfile(self): + self._used_sendfile = True + return True + +def wsgi_app(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return ['Hello World!'] + +def wsgi_app_file_wrapper(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return environ['wsgi.file_wrapper'](StringIO('foo')) + +class WSGIFileWrapperTests(TestCase): + """ + Test that the wsgi.file_wrapper works for the builting server. + """ + + def test_file_wrapper_uses_sendfile(self): + env = {'SERVER_PROTOCOL': 'HTTP/1.0'} + err = StringIO() + handler = FileWrapperHandler(None, StringIO(), err, env) + handler.run(wsgi_app_file_wrapper) + self.assert_(handler._used_sendfile) + + def test_file_wrapper_no_sendfile(self): + env = {'SERVER_PROTOCOL': 'HTTP/1.0'} + err = StringIO() + handler = FileWrapperHandler(None, StringIO(), err, env) + handler.run(wsgi_app) + self.failIf(handler._used_sendfile) + self.assertEqual(handler.stdout.getvalue().splitlines()[-1],'Hello World!')