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

File 7581-Streaming-HttpResponse-r16445.diff, 6.6 KB (added by Tai Lee, 7 years ago)

Update for trunk r16445.

  • django/http/__init__.py

     
    549549    status_code = 200
    550550
    551551    def __init__(self, content='', mimetype=None, status=None,
    552             content_type=None):
     552            content_type=None, stream_content=False):
    553553        # _headers is a mapping of the lower-case name to the original case of
    554554        # the header (required for working with legacy systems) and the header
    555555        # value.  Both the name of the header and its value are ASCII strings.
     
    560560        if not content_type:
    561561            content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
    562562                    self._charset)
    563         if not isinstance(content, basestring) and hasattr(content, '__iter__'):
    564             self._container = content
    565             self._is_string = False
    566         else:
    567             self._container = [content]
    568             self._is_string = True
     563        self._stream_content = stream_content
     564        self.content = content
    569565        self.cookies = SimpleCookie()
    570566        if status:
    571567            self.status_code = status
     
    663659        self.set_cookie(key, max_age=0, path=path, domain=domain,
    664660                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
    665661
     662    def _consume_content(self):
     663        if not self._is_string:
     664            self._container = [''.join(self._container)]
     665            self._is_string = True
     666
    666667    def _get_content(self):
     668        self._consume_content()
    667669        if self.has_header('Content-Encoding'):
    668670            return ''.join(self._container)
    669671        return smart_str(''.join(self._container), self._charset)
    670672
    671673    def _set_content(self, value):
    672         self._container = [value]
    673         self._is_string = True
     674        if not isinstance(value, basestring) and hasattr(value, '__iter__'):
     675            self._container = value
     676            self._is_string = False
     677            if not self._stream_content:
     678                self._consume_content()
     679        else:
     680            self._container = [value]
     681            self._is_string = True
    674682
    675683    content = property(_get_content, _set_content)
    676684
     685    def _get_content_generator(self):
     686        if not self._is_string:
     687            return (smart_str(item, self._charset) for item in self._container)
     688
     689    content_generator = property(_get_content_generator)
     690
    677691    def __iter__(self):
    678692        self._iterator = iter(self._container)
    679693        return self
  • django/utils/text.py

     
    187187    zfile.close()
    188188    return zbuf.getvalue()
    189189
     190# WARNING - be aware that compress_sequence does not achieve the same
     191# level of compression as compress_string
     192def compress_sequence(sequence):
     193    import cStringIO, gzip
     194    zbuf = cStringIO.StringIO()
     195    zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
     196    yield zbuf.getvalue()
     197    for item in sequence:
     198        position = zbuf.tell()
     199        zfile.write(item)
     200        zfile.flush()
     201        zbuf.seek(position)
     202        yield zbuf.read()
     203    position = zbuf.tell()
     204    zfile.close()
     205    zbuf.seek(position)
     206    yield zbuf.read()
     207
    190208ustring_re = re.compile(u"([\u0080-\uffff])")
    191209
    192210def javascript_quote(s, quote_double_quotes=False):
  • django/middleware/common.py

     
    112112        if settings.USE_ETAGS:
    113113            if response.has_header('ETag'):
    114114                etag = response['ETag']
    115             else:
     115            elif not response.content_generator:
    116116                etag = '"%s"' % hashlib.md5(response.content).hexdigest()
    117             if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
    118                 cookies = response.cookies
    119                 response = http.HttpResponseNotModified()
    120                 response.cookies = cookies
    121             else:
    122                 response['ETag'] = etag
     117            try:
     118                if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
     119                    cookies = response.cookies
     120                    response = http.HttpResponseNotModified()
     121                    response.cookies = cookies
     122                else:
     123                    response['ETag'] = etag
     124            except NameError:
     125                pass
    123126
    124127        return response
    125128
  • 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