From 6b95aa6fb549b3834b7feefc6fbe92f8a50da411 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Wed, 2 Mar 2011 10:40:48 +0000 Subject: [PATCH] Fixed #15531 -- Partially reverted [15701] due to compatibility issues with middlewares that modify content of responses. Thanks for the report, schinckel. Refs #15281. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15703 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/servers/basehttp.py | 25 +++++++++++++++- django/views/static.py | 33 ++------------------- tests/regressiontests/views/tests/static.py | 24 +++++---------- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 9e23688307..4e179dc7c0 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -19,7 +19,6 @@ from django.core.management.color import color_style from django.utils.http import http_date from django.utils._os import safe_join from django.views import static -from django.views.static import FileWrapper # for backwards compatibility, #15281 from django.contrib.staticfiles import handlers @@ -33,6 +32,30 @@ software_version = server_version + ' ' + sys_version class WSGIServerException(Exception): pass +class FileWrapper(object): + """Wrapper to convert file-like objects to iterables""" + + def __init__(self, filelike, blksize=8192): + self.filelike = filelike + self.blksize = blksize + if hasattr(filelike,'close'): + self.close = filelike.close + + def __getitem__(self,key): + data = self.filelike.read(self.blksize) + if data: + return data + raise IndexError + + def __iter__(self): + return self + + def next(self): + data = self.filelike.read(self.blksize) + if data: + return data + raise StopIteration + # Regular expression that matches `special' characters in parameters, the # existence of which force quoting of the parameter value. tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') diff --git a/django/views/static.py b/django/views/static.py index 96acc859f1..c058cd3ff8 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -9,39 +9,10 @@ import posixpath import re import urllib -from django.template import loader from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified - -from django.template import Template, Context, TemplateDoesNotExist +from django.template import loader, Template, Context, TemplateDoesNotExist from django.utils.http import http_date, parse_http_date - -class FileWrapper(object): - """ - Wrapper to convert file-like objects to iterables - """ - def __init__(self, filelike, blksize=8192): - self.filelike = filelike - self.blksize = blksize - if hasattr(filelike,'close'): - self.close = filelike.close - - def __getitem__(self,key): - data = self.filelike.read(self.blksize) - if data: - return data - raise IndexError - - def __iter__(self): - return self - - def next(self): - data = self.filelike.read(self.blksize) - if data: - return data - raise StopIteration - - def serve(request, path, document_root=None, show_indexes=False): """ Serve static files below a given point in the directory structure. @@ -85,7 +56,7 @@ def serve(request, path, document_root=None, show_indexes=False): if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), statobj.st_mtime, statobj.st_size): return HttpResponseNotModified(mimetype=mimetype) - response = HttpResponse(FileWrapper(open(fullpath, 'rb')), mimetype=mimetype) + response = HttpResponse(open(fullpath, 'rb').read(), mimetype=mimetype) response["Last-Modified"] = http_date(statobj.st_mtime) response["Content-Length"] = statobj.st_size if encoding: diff --git a/tests/regressiontests/views/tests/static.py b/tests/regressiontests/views/tests/static.py index 1c4f9ce85b..e3bc1643c5 100644 --- a/tests/regressiontests/views/tests/static.py +++ b/tests/regressiontests/views/tests/static.py @@ -26,18 +26,10 @@ class StaticTests(TestCase): for filename in media_files: response = self.client.get('/views/%s/%s' % (self.prefix, filename)) file_path = path.join(media_dir, filename) - content = str(response.content) - self.assertEquals(open(file_path).read(), content) - self.assertEquals(len(content), int(response['Content-Length'])) + self.assertEquals(open(file_path).read(), response.content) + self.assertEquals(len(response.content), int(response['Content-Length'])) self.assertEquals(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None)) - def test_serve_does_not_buffer_files(self): - "The static view uses an iterator - see #15281" - response = self.client.get('/views/%s/file.txt' % self.prefix) - # response objects can't be used as file-like objects when they are - # initialized with an iterator - self.assertRaises(Exception, response.write, 'more text') - def test_unknown_mime_type(self): response = self.client.get('/views/%s/file.unknown' % self.prefix) self.assertEquals('application/octet-stream', response['Content-Type']) @@ -76,9 +68,9 @@ class StaticTests(TestCase): response = self.client.get('/views/%s/%s' % (self.prefix, file_name), HTTP_IF_MODIFIED_SINCE=invalid_date) file = open(path.join(media_dir, file_name)) - content = str(response.content) - self.assertEquals(file.read(), content) - self.assertEquals(len(content), int(response['Content-Length'])) + self.assertEquals(file.read(), response.content) + self.assertEquals(len(response.content), + int(response['Content-Length'])) def test_invalid_if_modified_since2(self): """Handle even more bogus If-Modified-Since values gracefully @@ -90,10 +82,10 @@ class StaticTests(TestCase): invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT' response = self.client.get('/views/%s/%s' % (self.prefix, file_name), HTTP_IF_MODIFIED_SINCE=invalid_date) - content = str(response.content) file = open(path.join(media_dir, file_name)) - self.assertEquals(file.read(), content) - self.assertEquals(len(content), int(response['Content-Length'])) + self.assertEquals(file.read(), response.content) + self.assertEquals(len(response.content), + int(response['Content-Length'])) class StaticHelperTest(StaticTests):