Ticket #7581: streaming_response.3.diff

File streaming_response.3.diff, 8.1 KB (added by mrmachine, 7 years ago)

add stream_content argument.

  • django/http/__init__.py

     
    260260    status_code = 200
    261261
    262262    def __init__(self, content='', mimetype=None, status=None,
    263             content_type=None):
     263            content_type=None, stream_content=False):
    264264        from django.conf import settings
    265265        self._charset = settings.DEFAULT_CHARSET
    266266        if mimetype:
     
    268268        if not content_type:
    269269            content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
    270270                    settings.DEFAULT_CHARSET)
    271         if not isinstance(content, basestring) and hasattr(content, '__iter__'):
    272             self._container = content
    273             self._is_string = False
    274         else:
    275             self._container = [content]
    276             self._is_string = True
     271        self._stream_content = stream_content
     272        self.content = content
    277273        self.cookies = SimpleCookie()
    278274        if status:
    279275            self.status_code = status
     
    344340        self.set_cookie(key, max_age=0, path=path, domain=domain,
    345341                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
    346342
     343    def _consume_content(self):
     344        if not self._is_string:
     345            self._container = [''.join(self._container)]
     346            self._is_string = True
     347
    347348    def _get_content(self):
     349        self._consume_content()
    348350        if self.has_header('Content-Encoding'):
    349351            return ''.join(self._container)
    350352        return smart_str(''.join(self._container), self._charset)
    351353
    352354    def _set_content(self, value):
    353         self._container = [value]
    354         self._is_string = True
     355        if not isinstance(value, basestring) and hasattr(value, '__iter__'):
     356            self._container = value
     357            self._is_string = False
     358            if not self._stream_content:
     359                self._consume_content()
     360        else:
     361            self._container = [value]
     362            self._is_string = True
    355363
    356364    content = property(_get_content, _set_content)
    357365
     366    def _get_content_generator(self):
     367        if not self._is_string:
     368            return self._container
     369
     370    content_generator = property(_get_content_generator)
     371
    358372    def __iter__(self):
    359373        self._iterator = iter(self._container)
    360374        return self
  • django/http/utils.py

     
    3131    if request.method == 'HEAD':
    3232        response.content = ''
    3333    return response
     34
     35def set_content_length(request, response):
     36    """
     37    Ensures that we always have a Content-Length header, required by some
     38    handlers (WSGI), which don't permit chunked transfer encoding.
     39    """
     40    if not 'Content-Length' in response:
     41        response['Content-Length'] = str(len(response.content))
     42    return response
  • django/core/handlers/wsgi.py

     
    182182class WSGIHandler(BaseHandler):
    183183    initLock = Lock()
    184184    request_class = WSGIRequest
     185    response_fixes = [http.fix_location_header,
     186                      http.conditional_content_removal,
     187                      http.set_content_length]
    185188
    186189    def __call__(self, environ, start_response):
    187190        from django.conf import settings
  • django/utils/text.py

     
    175175    zfile.close()
    176176    return zbuf.getvalue()
    177177
     178def compress_sequence(sequence):
     179    import cStringIO, gzip
     180    zbuf = cStringIO.StringIO()
     181    zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
     182    yield zbuf.getvalue()
     183    for item in sequence:
     184        position = zbuf.tell()
     185        zfile.write(item)
     186        zfile.flush()
     187        zbuf.seek(position)
     188        yield zbuf.read()
     189
    178190ustring_re = re.compile(u"([\u0080-\uffff])")
    179191
    180192def javascript_quote(s, quote_double_quotes=False):
  • django/contrib/csrf/middleware.py

     
    8989                "' /></div>")
    9090
    9191            # Modify any POST forms
    92             response.content = _POST_FORM_RE.sub(add_csrf_field, response.content)
     92            if response.content_generator:
     93                response.content = (_POST_FORM_RE.sub(add_csrf_field, chunk) for chunk in response.content_generator)
     94            else:
     95                response.content = _POST_FORM_RE.sub(add_csrf_field, response.content)
    9396        return response
  • django/middleware/common.py

     
    107107        if settings.USE_ETAGS:
    108108            if response.has_header('ETag'):
    109109                etag = response['ETag']
    110             else:
     110            elif not response.content_generator:
    111111                etag = '"%s"' % md5.new(response.content).hexdigest()
    112             if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
    113                 cookies = response.cookies
    114                 response = http.HttpResponseNotModified()
    115                 response.cookies = cookies
    116             else:
    117                 response['ETag'] = etag
     112            try:
     113                if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
     114                    cookies = response.cookies
     115                    response = http.HttpResponseNotModified()
     116                    response.cookies = cookies
     117                else:
     118                    response['ETag'] = etag
     119            except NameError:
     120                pass
    118121
    119122        return response
    120123
  • 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',))
     
    3333        if not re_accepts_gzip.search(ae):
    3434            return response
    3535
    36         response.content = compress_string(response.content)
     36        if response.content_generator:
     37            response.content = compress_sequence(response.content_generator)
     38            del response['Content-Length']
     39        else:
     40            response.content = compress_string(response.content)
     41            response['Content-Length'] = str(len(response.content))
    3742        response['Content-Encoding'] = 'gzip'
    38         response['Content-Length'] = str(len(response.content))
    3943        return response
  • django/middleware/http.py

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