summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-06-18 10:51:38 +0200
committerClaude Paroz <claude@2xlibre.net>2016-06-27 10:44:57 +0200
commit9588718cd404d73b2be09241b424b539d8d8c66e (patch)
tree3ad0f2054fb540fd92ce9ae0125ed70e19eee2e8
parentca77b509059831b055a3b735ff77e042f8e1c0eb (diff)
Fixed #5897 -- Added the Content-Length response header in CommonMiddleware
Thanks Tim Graham for the review.
-rw-r--r--django/middleware/common.py4
-rw-r--r--docs/ref/middleware.txt6
-rw-r--r--docs/releases/1.11.txt3
-rw-r--r--tests/middleware/tests.py24
-rw-r--r--tests/project_template/test_settings.py1
-rw-r--r--tests/wsgi/tests.py11
6 files changed, 44 insertions, 5 deletions
diff --git a/django/middleware/common.py b/django/middleware/common.py
index 8cb00ff250..b705f72b81 100644
--- a/django/middleware/common.py
+++ b/django/middleware/common.py
@@ -123,6 +123,10 @@ class CommonMiddleware(MiddlewareMixin):
etag=unquote_etag(response['ETag']),
response=response,
)
+ # Add the Content-Length header to non-streaming responses if not
+ # already set.
+ if not response.streaming and not response.has_header('Content-Length'):
+ response['Content-Length'] = str(len(response.content))
return response
diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt
index 8b991d5ed8..371121c30e 100644
--- a/docs/ref/middleware.txt
+++ b/docs/ref/middleware.txt
@@ -66,6 +66,12 @@ Adds a few conveniences for perfectionists:
for each request by MD5-hashing the page content, and it'll take care of
sending ``Not Modified`` responses, if appropriate.
+* Sets the ``Content-Length`` header for non-streaming responses.
+
+.. versionchanged: 1.11
+
+ Older versions didn't set the ``Content-Length`` header.
+
.. attribute:: CommonMiddleware.response_redirect_class
Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt
index e5dcc47e24..23af4a4d60 100644
--- a/docs/releases/1.11.txt
+++ b/docs/releases/1.11.txt
@@ -197,6 +197,9 @@ Requests and Responses
* Added :meth:`QueryDict.fromkeys() <django.http.QueryDict.fromkeys>`.
+* :class:`~django.middleware.common.CommonMiddleware` now sets the
+ ``Content-Length`` response header for non-streaming responses.
+
Serialization
~~~~~~~~~~~~~
diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py
index f87bb9d71c..f9ef951b44 100644
--- a/tests/middleware/tests.py
+++ b/tests/middleware/tests.py
@@ -285,6 +285,27 @@ class CommonMiddlewareTest(SimpleTestCase):
second_res = CommonMiddleware().process_response(second_req, HttpResponse('content'))
self.assertEqual(second_res.status_code, 304)
+ # Tests for the Content-Length header
+
+ def test_content_length_header_added(self):
+ response = HttpResponse('content')
+ self.assertNotIn('Content-Length', response)
+ response = CommonMiddleware().process_response(HttpRequest(), response)
+ self.assertEqual(int(response['Content-Length']), len(response.content))
+
+ def test_content_length_header_not_added_for_streaming_response(self):
+ response = StreamingHttpResponse('content')
+ self.assertNotIn('Content-Length', response)
+ response = CommonMiddleware().process_response(HttpRequest(), response)
+ self.assertNotIn('Content-Length', response)
+
+ def test_content_length_header_not_changed(self):
+ response = HttpResponse()
+ bad_content_length = len(response.content) + 10
+ response['Content-Length'] = bad_content_length
+ response = CommonMiddleware().process_response(HttpRequest(), response)
+ self.assertEqual(int(response['Content-Length']), bad_content_length)
+
# Other tests
@override_settings(DISALLOWED_USER_AGENTS=[re.compile(r'foo')])
@@ -445,6 +466,9 @@ class ConditionalGetMiddlewareTest(SimpleTestCase):
def test_content_length_header_added(self):
content_length = len(self.resp.content)
+ # Already set by CommonMiddleware, remove it to check that
+ # ConditionalGetMiddleware readds it.
+ del self.resp['Content-Length']
self.assertNotIn('Content-Length', self.resp)
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
self.assertIn('Content-Length', self.resp)
diff --git a/tests/project_template/test_settings.py b/tests/project_template/test_settings.py
index d153c4d95f..a0047dd836 100644
--- a/tests/project_template/test_settings.py
+++ b/tests/project_template/test_settings.py
@@ -41,6 +41,7 @@ class TestStartProjectSettings(TestCase):
response = self.client.get('/empty/')
headers = sorted(response.serialize_headers().split(b'\r\n'))
self.assertEqual(headers, [
+ b'Content-Length: 0',
b'Content-Type: text/html; charset=utf-8',
b'X-Frame-Options: SAMEORIGIN',
])
diff --git a/tests/wsgi/tests.py b/tests/wsgi/tests.py
index f472d4fab9..03ac7ee706 100644
--- a/tests/wsgi/tests.py
+++ b/tests/wsgi/tests.py
@@ -41,11 +41,12 @@ class WSGITest(SimpleTestCase):
self.assertEqual(response_data["status"], "200 OK")
self.assertEqual(
- response_data["headers"],
- [('Content-Type', 'text/html; charset=utf-8')])
- self.assertEqual(
- bytes(response),
- b"Content-Type: text/html; charset=utf-8\r\n\r\nHello World!")
+ set(response_data["headers"]),
+ {('Content-Length', '12'), ('Content-Type', 'text/html; charset=utf-8')})
+ self.assertTrue(bytes(response) in [
+ b"Content-Length: 12\r\nContent-Type: text/html; charset=utf-8\r\n\r\nHello World!",
+ b"Content-Type: text/html; charset=utf-8\r\nContent-Length: 12\r\n\r\nHello World!"
+ ])
def test_file_wrapper(self):
"""