Commit 7cfe8e8f authored by Claude Paroz's avatar Claude Paroz
Browse files

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.
parent e2b4eddc
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -744,6 +744,16 @@ class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
class HttpResponseNotModified(HttpResponse):
    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):
    status_code = 400

+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ def serve(request, path, document_root=None, show_indexes=False):
    mimetype = mimetype or 'application/octet-stream'
    if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
                              statobj.st_mtime, statobj.st_size):
        return HttpResponseNotModified(content_type=mimetype)
        return HttpResponseNotModified()
    with open(fullpath, 'rb') as f:
        response = HttpResponse(f.read(), content_type=mimetype)
    response["Last-Modified"] = http_date(statobj.st_mtime)
+3 −2
Original line number Diff line number Diff line
@@ -743,8 +743,9 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in

.. class:: HttpResponseNotModified

    The constructor doesn't take any arguments. Use this to designate that a
    page hasn't been modified since the user's last request (status code 304).
    The constructor doesn't take any arguments and no content should be added
    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

+11 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ import pickle

from django.core.exceptions import SuspiciousOperation
from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
                         HttpResponsePermanentRedirect,
                         HttpResponsePermanentRedirect, HttpResponseNotModified,
                         SimpleCookie, BadHeaderError,
                         parse_cookie)
from django.utils import six
@@ -330,6 +330,16 @@ class HttpResponseTests(unittest.TestCase):
                              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):
    def test_encode(self):
        """