mirror of https://github.com/django/django.git
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
This commit is contained in:
parent
ec193224d3
commit
6b95aa6fb5
|
@ -19,7 +19,6 @@ from django.core.management.color import color_style
|
||||||
from django.utils.http import http_date
|
from django.utils.http import http_date
|
||||||
from django.utils._os import safe_join
|
from django.utils._os import safe_join
|
||||||
from django.views import static
|
from django.views import static
|
||||||
from django.views.static import FileWrapper # for backwards compatibility, #15281
|
|
||||||
|
|
||||||
from django.contrib.staticfiles import handlers
|
from django.contrib.staticfiles import handlers
|
||||||
|
|
||||||
|
@ -33,6 +32,30 @@ software_version = server_version + ' ' + sys_version
|
||||||
class WSGIServerException(Exception):
|
class WSGIServerException(Exception):
|
||||||
pass
|
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
|
# Regular expression that matches `special' characters in parameters, the
|
||||||
# existence of which force quoting of the parameter value.
|
# existence of which force quoting of the parameter value.
|
||||||
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
|
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
|
||||||
|
|
|
@ -9,39 +9,10 @@ import posixpath
|
||||||
import re
|
import re
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from django.template import loader
|
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
|
from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
|
||||||
|
from django.template import loader, Template, Context, TemplateDoesNotExist
|
||||||
from django.template import Template, Context, TemplateDoesNotExist
|
|
||||||
from django.utils.http import http_date, parse_http_date
|
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):
|
def serve(request, path, document_root=None, show_indexes=False):
|
||||||
"""
|
"""
|
||||||
Serve static files below a given point in the directory structure.
|
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'),
|
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
|
||||||
statobj.st_mtime, statobj.st_size):
|
statobj.st_mtime, statobj.st_size):
|
||||||
return HttpResponseNotModified(mimetype=mimetype)
|
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["Last-Modified"] = http_date(statobj.st_mtime)
|
||||||
response["Content-Length"] = statobj.st_size
|
response["Content-Length"] = statobj.st_size
|
||||||
if encoding:
|
if encoding:
|
||||||
|
|
|
@ -26,18 +26,10 @@ class StaticTests(TestCase):
|
||||||
for filename in media_files:
|
for filename in media_files:
|
||||||
response = self.client.get('/views/%s/%s' % (self.prefix, filename))
|
response = self.client.get('/views/%s/%s' % (self.prefix, filename))
|
||||||
file_path = path.join(media_dir, filename)
|
file_path = path.join(media_dir, filename)
|
||||||
content = str(response.content)
|
self.assertEquals(open(file_path).read(), response.content)
|
||||||
self.assertEquals(open(file_path).read(), content)
|
self.assertEquals(len(response.content), int(response['Content-Length']))
|
||||||
self.assertEquals(len(content), int(response['Content-Length']))
|
|
||||||
self.assertEquals(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))
|
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):
|
def test_unknown_mime_type(self):
|
||||||
response = self.client.get('/views/%s/file.unknown' % self.prefix)
|
response = self.client.get('/views/%s/file.unknown' % self.prefix)
|
||||||
self.assertEquals('application/octet-stream', response['Content-Type'])
|
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),
|
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
|
||||||
HTTP_IF_MODIFIED_SINCE=invalid_date)
|
HTTP_IF_MODIFIED_SINCE=invalid_date)
|
||||||
file = open(path.join(media_dir, file_name))
|
file = open(path.join(media_dir, file_name))
|
||||||
content = str(response.content)
|
self.assertEquals(file.read(), response.content)
|
||||||
self.assertEquals(file.read(), content)
|
self.assertEquals(len(response.content),
|
||||||
self.assertEquals(len(content), int(response['Content-Length']))
|
int(response['Content-Length']))
|
||||||
|
|
||||||
def test_invalid_if_modified_since2(self):
|
def test_invalid_if_modified_since2(self):
|
||||||
"""Handle even more bogus If-Modified-Since values gracefully
|
"""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'
|
invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT'
|
||||||
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
|
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
|
||||||
HTTP_IF_MODIFIED_SINCE=invalid_date)
|
HTTP_IF_MODIFIED_SINCE=invalid_date)
|
||||||
content = str(response.content)
|
|
||||||
file = open(path.join(media_dir, file_name))
|
file = open(path.join(media_dir, file_name))
|
||||||
self.assertEquals(file.read(), content)
|
self.assertEquals(file.read(), response.content)
|
||||||
self.assertEquals(len(content), int(response['Content-Length']))
|
self.assertEquals(len(response.content),
|
||||||
|
int(response['Content-Length']))
|
||||||
|
|
||||||
|
|
||||||
class StaticHelperTest(StaticTests):
|
class StaticHelperTest(StaticTests):
|
||||||
|
|
Loading…
Reference in New Issue