Code

Ticket #2504: get_content_length2.diff

File get_content_length2.diff, 4.6 KB (added by frasern, 7 years ago)

Supercedes get_content_length.diff

Line 
1Index: django/http/__init__.py
2===================================================================
3--- django/http/__init__.py     (revision 6286)
4+++ django/http/__init__.py     (working copy)
5@@ -240,12 +240,14 @@
6         if not content_type:
7             content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
8                     settings.DEFAULT_CHARSET)
9-        if not isinstance(content, basestring) and hasattr(content, '__iter__'):
10+        self._is_file = False
11+        if isinstance(content, file):
12             self._container = content
13-            self._is_string = False
14+            self._is_file = True
15+        elif not isinstance(content, basestring) and hasattr(content, '__iter__'):
16+            self._container = list(content)
17         else:
18             self._container = [content]
19-            self._is_string = True
20         self._headers = {'content-type': content_type}
21         self.cookies = SimpleCookie()
22         if status:
23@@ -299,14 +301,21 @@
24 
25     def _get_content(self):
26         content = smart_str(''.join(self._container), self._charset)
27+        self.content = content
28         return content
29 
30     def _set_content(self, value):
31         self._container = [value]
32-        self._is_string = True
33+        self._is_file = False
34 
35     content = property(_get_content, _set_content)
36 
37+    def get_content_length(self):
38+        if isinstance(self._container, file):
39+            if os.path.exists(self._container.name):
40+                return os.path.getsize(self._container.name)
41+        return len(self.content)
42+
43     def __iter__(self):
44         self._iterator = iter(self._container)
45         return self
46@@ -324,7 +333,7 @@
47     # The remaining methods partially implement the file-like object interface.
48     # See http://docs.python.org/lib/bltin-file-objects.html
49     def write(self, content):
50-        if not self._is_string:
51+        if self._is_file:
52             raise Exception, "This %s instance is not writable" % self.__class__
53         self._container.append(content)
54 
55@@ -332,7 +341,7 @@
56         pass
57 
58     def tell(self):
59-        if not self._is_string:
60+        if self._is_file:
61             raise Exception, "This %s instance cannot tell its position" % self.__class__
62         return sum([len(chunk) for chunk in self._container])
63 
64Index: django/middleware/http.py
65===================================================================
66--- django/middleware/http.py   (revision 6286)
67+++ django/middleware/http.py   (working copy)
68@@ -13,7 +13,9 @@
69     def process_response(self, request, response):
70         response['Date'] = formatdate()[:26] + "GMT"
71         if not response.has_header('Content-Length'):
72-            response['Content-Length'] = str(len(response.content))
73+            content_length = response.get_content_length()
74+            if content_length is not None:
75+                response['Content-Length'] = str(content_length)
76 
77         if response.has_header('ETag'):
78             if_none_match = request.META.get('HTTP_IF_NONE_MATCH', None)
79Index: tests/regressiontests/httpwrappers/tests.py
80===================================================================
81--- tests/regressiontests/httpwrappers/tests.py (revision 6286)
82+++ tests/regressiontests/httpwrappers/tests.py (working copy)
83@@ -391,9 +391,38 @@
84 >>> q.getlist('foo')
85 [u'bar', u'\ufffd']
86 
87+
88+>>> r = HttpResponse()
89+>>> r.get_content_length()
90+0
91+
92+>>> r = HttpResponse('foo')
93+>>> r.get_content_length()
94+3
95+
96+>>> r = HttpResponse('foo')
97+>>> r.write('bar')
98+>>> r.get_content_length()
99+6
100+
101+>>> r = HttpResponse(['foo', 'bar', 'foobar'])
102+>>> r.get_content_length()
103+12
104+
105+>>> r = HttpResponse(file(__file__))
106+>>> assert r.get_content_length() > 0
107+
108+>>> def ten_foos():
109+...     for i in range(10): yield 'foo'
110+>>> r = HttpResponse(ten_foos())
111+>>> r.get_content_length()
112+30
113+>>> print r.content
114+foofoofoofoofoofoofoofoofoofoo
115+
116 """
117 
118-from django.http import QueryDict
119+from django.http import QueryDict, HttpResponse
120 
121 if __name__ == "__main__":
122     import doctest
123Index: docs/request_response.txt
124===================================================================
125--- docs/request_response.txt   (revision 6286)
126+++ docs/request_response.txt   (working copy)
127@@ -431,6 +431,9 @@
128 ``write(content)``, ``flush()`` and ``tell()``
129     These methods make an ``HttpResponse`` instance a file-like object.
130 
131+``get_content_length()``
132+    Returns the current length of ``content``.
133+
134 .. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
135 
136 HttpResponse subclasses