Fixed #11340 -- Prevented HttpResponseNotModified to have content/content-type

The HTTP 1.1 spec tells that the 304 response MUST NOT contain a
message body.
Thanks aparajita for the report.
This commit is contained in:
Claude Paroz 2012-08-22 18:06:03 +02:00
parent e2b4eddc11
commit 7cfe8e8fce
4 changed files with 25 additions and 4 deletions

View File

@ -744,6 +744,16 @@ class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
class HttpResponseNotModified(HttpResponse): class HttpResponseNotModified(HttpResponse):
status_code = 304 status_code = 304
def __init__(self, *args, **kwargs):
super(HttpResponseNotModified, self).__init__(*args, **kwargs)
del self['content-type']
@HttpResponse.content.setter
def content(self, value):
if value:
raise AttributeError("You cannot set content to a 304 (Not Modified) response")
self._container = []
class HttpResponseBadRequest(HttpResponse): class HttpResponseBadRequest(HttpResponse):
status_code = 400 status_code = 400

View File

@ -61,7 +61,7 @@ def serve(request, path, document_root=None, show_indexes=False):
mimetype = mimetype or 'application/octet-stream' mimetype = mimetype or 'application/octet-stream'
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
statobj.st_mtime, statobj.st_size): statobj.st_mtime, statobj.st_size):
return HttpResponseNotModified(content_type=mimetype) return HttpResponseNotModified()
with open(fullpath, 'rb') as f: with open(fullpath, 'rb') as f:
response = HttpResponse(f.read(), content_type=mimetype) response = HttpResponse(f.read(), content_type=mimetype)
response["Last-Modified"] = http_date(statobj.st_mtime) response["Last-Modified"] = http_date(statobj.st_mtime)

View File

@ -743,8 +743,9 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
.. class:: HttpResponseNotModified .. class:: HttpResponseNotModified
The constructor doesn't take any arguments. Use this to designate that a The constructor doesn't take any arguments and no content should be added
page hasn't been modified since the user's last request (status code 304). to this response. Use this to designate that a page hasn't been modified
since the user's last request (status code 304).
.. class:: HttpResponseBadRequest .. class:: HttpResponseBadRequest

View File

@ -6,7 +6,7 @@ import pickle
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.http import (QueryDict, HttpResponse, HttpResponseRedirect, from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
HttpResponsePermanentRedirect, HttpResponsePermanentRedirect, HttpResponseNotModified,
SimpleCookie, BadHeaderError, SimpleCookie, BadHeaderError,
parse_cookie) parse_cookie)
from django.utils import six from django.utils import six
@ -330,6 +330,16 @@ class HttpResponseTests(unittest.TestCase):
HttpResponsePermanentRedirect, url) HttpResponsePermanentRedirect, url)
class HttpResponseSubclassesTests(unittest.TestCase):
def test_not_modified(self):
response = HttpResponseNotModified()
self.assertEqual(response.status_code, 304)
# 304 responses should not have content/content-type
with self.assertRaises(AttributeError):
response.content = "Hello dear"
self.assertNotIn('content-type', response)
class CookieTests(unittest.TestCase): class CookieTests(unittest.TestCase):
def test_encode(self): def test_encode(self):
""" """