Commit 6b95aa6f authored by Jannis Leidel's avatar Jannis Leidel
Browse files

Fixed #15531 -- Partially reverted [15701] due to compatibility issues with...

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
parent ec193224
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -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'[ \(\)<>@,;:\\"/\[\]\?=]')
+2 −31
Original line number Diff line number Diff line
@@ -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:
+8 −16
Original line number Diff line number Diff line
@@ -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):