Reduced CookieStorage.max_cookie_size to 75% of 4K to be nice to Internet Explorer

Internet Explorer, up to at least version 7, allows only 4K cookie data *per
domain*, rather than per cookie, so we ensure that stored messages leave
some room for other cookies.




git-svn-id: http://code.djangoproject.com/svn/django/trunk@12287 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2010-01-24 00:04:02 +00:00
parent 63d072581c
commit e6c5599494
3 changed files with 18 additions and 6 deletions

View File

@ -1,10 +1,11 @@
import hmac import hmac
from django.conf import settings from django.conf import settings
from django.utils.hashcompat import sha_hmac
from django.contrib.messages import constants from django.contrib.messages import constants
from django.contrib.messages.storage.base import BaseStorage, Message from django.contrib.messages.storage.base import BaseStorage, Message
from django.http import CompatCookie
from django.utils import simplejson as json from django.utils import simplejson as json
from django.utils.hashcompat import sha_hmac
class MessageEncoder(json.JSONEncoder): class MessageEncoder(json.JSONEncoder):
@ -46,7 +47,10 @@ class CookieStorage(BaseStorage):
Stores messages in a cookie. Stores messages in a cookie.
""" """
cookie_name = 'messages' cookie_name = 'messages'
max_cookie_size = 4096 # We should be able to store 4K in a cookie, but Internet Explorer
# imposes 4K as the *total* limit for a domain. To allow other
# cookies, we go for 3/4 of 4K.
max_cookie_size = 3072
not_finished = '__messagesnotfinished__' not_finished = '__messagesnotfinished__'
def _get(self, *args, **kwargs): def _get(self, *args, **kwargs):

View File

@ -69,19 +69,25 @@ class CookieTest(BaseTest):
storage = self.get_storage() storage = self.get_storage()
response = self.get_response() response = self.get_response()
# When storing as a cookie, the cookie has constant overhead of approx
# 54 chars, and each message has a constant overhead of about 37 chars
# and a variable overhead of zero in the best case. We aim for a message
# size which will fit 4 messages into the cookie, but not 5.
# See also FallbackTest.test_session_fallback
msg_size = int((CookieStorage.max_cookie_size - 54) / 4.5 - 37)
for i in range(5): for i in range(5):
storage.add(constants.INFO, str(i) * 900) storage.add(constants.INFO, str(i) * msg_size)
unstored_messages = storage.update(response) unstored_messages = storage.update(response)
cookie_storing = self.stored_messages_count(storage, response) cookie_storing = self.stored_messages_count(storage, response)
self.assertEqual(cookie_storing, 4) self.assertEqual(cookie_storing, 4)
self.assertEqual(len(unstored_messages), 1) self.assertEqual(len(unstored_messages), 1)
self.assert_(unstored_messages[0].message == '0' * 900) self.assert_(unstored_messages[0].message == '0' * msg_size)
def test_json_encoder_decoder(self): def test_json_encoder_decoder(self):
""" """
Tests that an complex nested data structure containing Message Tests that a complex nested data structure containing Message
instances is properly encoded/decoded by the custom JSON instances is properly encoded/decoded by the custom JSON
encoder/decoder classes. encoder/decoder classes.
""" """

View File

@ -147,8 +147,10 @@ class FallbackTest(BaseTest):
storage = self.get_storage() storage = self.get_storage()
response = self.get_response() response = self.get_response()
# see comment in CookieText.test_cookie_max_length
msg_size = int((CookieStorage.max_cookie_size - 54) / 4.5 - 37)
for i in range(5): for i in range(5):
storage.add(constants.INFO, str(i) * 900) storage.add(constants.INFO, str(i) * msg_size)
storage.update(response) storage.update(response)
cookie_storing = self.stored_cookie_messages_count(storage, response) cookie_storing = self.stored_cookie_messages_count(storage, response)