Ticket #7581: 7581-Streaming-HttpResponse-r11381.diff

File 7581-Streaming-HttpResponse-r11381.diff, 7.2 KB (added by Tai Lee, 10 years ago)

Updated for trunk r11381.

  • django/http/__init__.py

     
    272272    status_code = 200
    273273
    274274    def __init__(self, content='', mimetype=None, status=None,
    275             content_type=None):
     275            content_type=None, stream_content=False):
    276276        from django.conf import settings
    277277        self._charset = settings.DEFAULT_CHARSET
    278278        if mimetype:
     
    280280        if not content_type:
    281281            content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
    282282                    settings.DEFAULT_CHARSET)
    283         if not isinstance(content, basestring) and hasattr(content, '__iter__'):
    284             self._container = content
    285             self._is_string = False
    286         else:
    287             self._container = [content]
    288             self._is_string = True
     283        self._stream_content = stream_content
     284        self.content = content
    289285        self.cookies = SimpleCookie()
    290286        if status:
    291287            self.status_code = status
     
    359355        self.set_cookie(key, max_age=0, path=path, domain=domain,
    360356                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
    361357
     358    def _consume_content(self):
     359        if not self._is_string:
     360            self._container = [''.join(self._container)]
     361            self._is_string = True
     362
    362363    def _get_content(self):
     364        self._consume_content()
    363365        if self.has_header('Content-Encoding'):
    364366            return ''.join(self._container)
    365367        return smart_str(''.join(self._container), self._charset)
    366368
    367369    def _set_content(self, value):
    368         self._container = [value]
    369         self._is_string = True
     370        if not isinstance(value, basestring) and hasattr(value, '__iter__'):
     371            self._container = value
     372            self._is_string = False
     373            if not self._stream_content:
     374                self._consume_content()
     375        else:
     376            self._container = [value]
     377            self._is_string = True
    370378
    371379    content = property(_get_content, _set_content)
    372380
     381    def _get_content_generator(self):
     382        if not self._is_string:
     383            return self._container
     384
     385    content_generator = property(_get_content_generator)
     386
    373387    def __iter__(self):
    374388        self._iterator = iter(self._container)
    375389        return self
  • django/contrib/csrf/middleware.py

     
    101101                "' /></div>")
    102102
    103103            # Modify any POST forms
    104             response.content = _POST_FORM_RE.sub(add_csrf_field, response.content)
     104            if response.content_generator:
     105                response.content = (_POST_FORM_RE.sub(add_csrf_field, chunk) for chunk in response.content_generator)
     106            else:
     107                response.content = _POST_FORM_RE.sub(add_csrf_field, response.content)
    105108        return response
    106109
    107110class CsrfMiddleware(CsrfViewMiddleware, CsrfResponseMiddleware):
  • django/utils/text.py

     
    176176    zfile.close()
    177177    return zbuf.getvalue()
    178178
     179# WARNING - be aware that compress_sequence does not achieve the same
     180# level of compression as compress_string
     181def compress_sequence(sequence):
     182    import cStringIO, gzip
     183    zbuf = cStringIO.StringIO()
     184    zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
     185    yield zbuf.getvalue()
     186    for item in sequence:
     187        position = zbuf.tell()
     188        zfile.write(item)
     189        zfile.flush()
     190        zbuf.seek(position)
     191        yield zbuf.read()
     192    position = zbuf.tell()
     193    zfile.close()
     194    zbuf.seek(position)
     195    yield zbuf.read()
     196
    179197ustring_re = re.compile(u"([\u0080-\uffff])")
    180198
    181199def javascript_quote(s, quote_double_quotes=False):
  • django/middleware/common.py

     
    100100        if settings.USE_ETAGS:
    101101            if response.has_header('ETag'):
    102102                etag = response['ETag']
    103             else:
     103            elif not response.content_generator:
    104104                etag = '"%s"' % md5_constructor(response.content).hexdigest()
    105             if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
    106                 cookies = response.cookies
    107                 response = http.HttpResponseNotModified()
    108                 response.cookies = cookies
    109             else:
    110                 response['ETag'] = etag
     105            try:
     106                if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
     107                    cookies = response.cookies
     108                    response = http.HttpResponseNotModified()
     109                    response.cookies = cookies
     110                else:
     111                    response['ETag'] = etag
     112            except NameError:
     113                pass
    111114
    112115        return response
    113116
  • django/middleware/gzip.py

     
    11import re
    22
    3 from django.utils.text import compress_string
     3from django.utils.text import compress_sequence, compress_string
    44from django.utils.cache import patch_vary_headers
    55
    66re_accepts_gzip = re.compile(r'\bgzip\b')
     
    1313    """
    1414    def process_response(self, request, response):
    1515        # It's not worth compressing non-OK or really short responses.
    16         if response.status_code != 200 or len(response.content) < 200:
     16        if response.status_code != 200 or (not response.content_generator and len(response.content) < 200):
    1717            return response
    1818
    1919        patch_vary_headers(response, ('Accept-Encoding',))
     
    3232        if not re_accepts_gzip.search(ae):
    3333            return response
    3434
    35         response.content = compress_string(response.content)
     35        if response.content_generator:
     36            response.content = compress_sequence(response.content_generator)
     37            del response['Content-Length']
     38        else:
     39            response.content = compress_string(response.content)
     40            response['Content-Length'] = str(len(response.content))
    3641        response['Content-Encoding'] = 'gzip'
    37         response['Content-Length'] = str(len(response.content))
    3842        return response
  • django/middleware/http.py

     
    1111    """
    1212    def process_response(self, request, response):
    1313        response['Date'] = http_date()
    14         if not response.has_header('Content-Length'):
     14        if not response.has_header('Content-Length') and not response.content_generator:
    1515            response['Content-Length'] = str(len(response.content))
    1616
    1717        if response.has_header('ETag'):
Back to Top