Code

Ticket #2504: get_content_length.diff

File get_content_length.diff, 3.2 KB (added by frasern, 7 years ago)
Line 
1Index: django/http/__init__.py
2===================================================================
3--- django/http/__init__.py     (revision 6286)
4+++ django/http/__init__.py     (working copy)
5@@ -307,6 +307,17 @@
6 
7     content = property(_get_content, _set_content)
8 
9+    def get_content_length(self):
10+        if isinstance(self._container, file):
11+            if os.path.exists(self._container.name):
12+                return os.path.getsize(self._container.name)
13+            else:
14+                return None
15+        elif isinstance(self._container, (list, tuple)):
16+            return len(self.content)
17+        else:
18+            return None
19+
20     def __iter__(self):
21         self._iterator = iter(self._container)
22         return self
23Index: django/middleware/http.py
24===================================================================
25--- django/middleware/http.py   (revision 6286)
26+++ django/middleware/http.py   (working copy)
27@@ -13,7 +13,9 @@
28     def process_response(self, request, response):
29         response['Date'] = formatdate()[:26] + "GMT"
30         if not response.has_header('Content-Length'):
31-            response['Content-Length'] = str(len(response.content))
32+            content_length = response.get_content_length()
33+            if content_length is not None:
34+                response['Content-Length'] = str(content_length)
35 
36         if response.has_header('ETag'):
37             if_none_match = request.META.get('HTTP_IF_NONE_MATCH', None)
38Index: tests/regressiontests/httpwrappers/tests.py
39===================================================================
40--- tests/regressiontests/httpwrappers/tests.py (revision 6286)
41+++ tests/regressiontests/httpwrappers/tests.py (working copy)
42@@ -391,9 +391,37 @@
43 >>> q.getlist('foo')
44 [u'bar', u'\ufffd']
45 
46+
47+>>> r = HttpResponse()
48+>>> r.get_content_length()
49+0
50+
51+>>> r = HttpResponse('foo')
52+>>> r.get_content_length()
53+3
54+
55+>>> r = HttpResponse('foo')
56+>>> r.write('bar')
57+>>> r.get_content_length()
58+6
59+
60+>>> r = HttpResponse(['foo', 'bar', 'foobar'])
61+>>> r.get_content_length()
62+12
63+
64+>>> r = HttpResponse(file(__file__))
65+>>> assert r.get_content_length() > 0
66+
67+>>> def ten_foos():
68+...     for i in range(10): yield 'foo'
69+>>> r = HttpResponse(ten_foos())
70+>>> assert r.get_content_length() is None
71+>>> print r.content
72+foofoofoofoofoofoofoofoofoofoo
73+
74 """
75 
76-from django.http import QueryDict
77+from django.http import QueryDict, HttpResponse
78 
79 if __name__ == "__main__":
80     import doctest
81Index: docs/request_response.txt
82===================================================================
83--- docs/request_response.txt   (revision 6286)
84+++ docs/request_response.txt   (working copy)
85@@ -431,6 +431,12 @@
86 ``write(content)``, ``flush()`` and ``tell()``
87     These methods make an ``HttpResponse`` instance a file-like object.
88 
89+``get_content_length()``
90+    Calculates the current length of ``content``. If a file was passed into
91+    ``__init__``, its system filesize is returned. If a non-fixed size iterator
92+    was passed into ``__init__``, then ``None`` will be returned because the size
93+    of ``content`` cannot necessarily be determined.
94+
95 .. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
96 
97 HttpResponse subclasses