summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Christopher Henry <k@severian.com>2016-10-11 00:08:37 -0400
committerTim Graham <timograham@gmail.com>2016-10-12 14:43:25 -0400
commitbd7237d7ec5bb66add624a0cf31ac85f9aceadce (patch)
tree467b143b109161093901358b01171fff756d872a
parentb2f9db1637021f5a0a0c201017f6536243ed203f (diff)
Fixed #19705 -- Set proper headers on conditional Not Modified responses.
-rw-r--r--django/utils/cache.py21
-rw-r--r--tests/middleware/tests.py22
2 files changed, 36 insertions, 7 deletions
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 8d0ce4dac5..0f6232b51b 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -122,14 +122,21 @@ def _precondition_failed(request):
def _not_modified(request, response=None):
+ new_response = HttpResponseNotModified()
if response:
- # We need to keep the cookies, see ticket #4994.
- cookies = response.cookies
- response = HttpResponseNotModified()
- response.cookies = cookies
- return response
- else:
- return HttpResponseNotModified()
+ # Preserve the headers required by Section 4.1 of RFC 7232, as well as
+ # Last-Modified.
+ for header in ('Cache-Control', 'Content-Location', 'Date', 'ETag', 'Expires', 'Last-Modified', 'Vary'):
+ if header in response:
+ new_response[header] = response[header]
+
+ # Preserve cookies as per the cookie specification: "If a proxy server
+ # receives a response which contains a Set-cookie header, it should
+ # propagate the Set-cookie header to the client, regardless of whether
+ # the response was 304 (Not Modified) or 200 (OK).
+ # https://curl.haxx.se/rfc/cookie_spec.html
+ new_response.cookies = response.cookies
+ return new_response
def get_conditional_response(request, etag=None, last_modified=None, response=None):
diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py
index 7bf53cfdeb..a9cb1f31ea 100644
--- a/tests/middleware/tests.py
+++ b/tests/middleware/tests.py
@@ -614,6 +614,28 @@ class ConditionalGetMiddlewareTest(SimpleTestCase):
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
self.assertEqual(self.resp.status_code, 400)
+ def test_not_modified_headers(self):
+ """
+ The 304 Not Modified response should include only the headers required
+ by section 4.1 of RFC 7232, Last-Modified, and the cookies.
+ """
+ self.req.META['HTTP_IF_NONE_MATCH'] = self.resp['ETag'] = '"spam"'
+ self.resp['Date'] = 'Sat, 12 Feb 2011 17:35:44 GMT'
+ self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:35:44 GMT'
+ self.resp['Expires'] = 'Sun, 13 Feb 2011 17:35:44 GMT'
+ self.resp['Vary'] = 'Cookie'
+ self.resp['Cache-Control'] = 'public'
+ self.resp['Content-Location'] = '/alt'
+ self.resp['Content-Language'] = 'en' # shouldn't be preserved
+ self.resp.set_cookie('key', 'value')
+
+ new_response = ConditionalGetMiddleware().process_response(self.req, self.resp)
+ self.assertEqual(new_response.status_code, 304)
+ for header in ('Cache-Control', 'Content-Location', 'Date', 'ETag', 'Expires', 'Last-Modified', 'Vary'):
+ self.assertEqual(new_response[header], self.resp[header])
+ self.assertEqual(new_response.cookies, self.resp.cookies)
+ self.assertNotIn('Content-Language', new_response)
+
class XFrameOptionsMiddlewareTest(SimpleTestCase):
"""