summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorDavid Wobrock <david.wobrock@gmail.com>2023-03-08 17:39:26 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-03-27 09:22:00 +0200
commit21757bbdcd6ef31f2a4092fa1bd55dff29214c7a (patch)
treecda6c52556354e30637ca7f2a16457c413a01d4b /django
parent9d0c878abf9249da6e16f1acfec311498dc9f368 (diff)
downloaddjango-21757bbdcd6ef31f2a4092fa1bd55dff29214c7a.tar.gz
Refs #28948 -- Removed superfluous messages from cookie through bisect.
Diffstat (limited to 'django')
-rw-r--r--django/contrib/messages/storage/cookie.py67
1 files changed, 56 insertions, 11 deletions
diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py
index b493b207c8..2008b31843 100644
--- a/django/contrib/messages/storage/cookie.py
+++ b/django/contrib/messages/storage/cookie.py
@@ -144,20 +144,31 @@ class CookieStorage(BaseStorage):
# adds its own overhead, which we must account for.
cookie = SimpleCookie() # create outside the loop
- def stored_length(val):
- return len(cookie.value_encode(val)[1])
+ def is_too_large_for_cookie(data):
+ return data and len(cookie.value_encode(data)[1]) > self.max_cookie_size
- while encoded_data and stored_length(encoded_data) > self.max_cookie_size:
+ def compute_msg(some_serialized_msg):
+ return self._encode_parts(
+ some_serialized_msg + [self.not_finished_json],
+ encode_empty=True,
+ )
+
+ if is_too_large_for_cookie(encoded_data):
if remove_oldest:
- unstored_messages.append(messages.pop(0))
- serialized_messages.pop(0)
+ idx = bisect_keep_right(
+ serialized_messages,
+ fn=lambda m: is_too_large_for_cookie(compute_msg(m)),
+ )
+ unstored_messages = messages[:idx]
+ encoded_data = compute_msg(serialized_messages[idx:])
else:
- unstored_messages.insert(0, messages.pop())
- serialized_messages.pop()
- encoded_data = self._encode_parts(
- serialized_messages + [self.not_finished_json],
- encode_empty=bool(unstored_messages),
- )
+ idx = bisect_keep_left(
+ serialized_messages,
+ fn=lambda m: is_too_large_for_cookie(compute_msg(m)),
+ )
+ unstored_messages = messages[idx:]
+ encoded_data = compute_msg(serialized_messages[:idx])
+
self._update_cookie(encoded_data, response)
return unstored_messages
@@ -201,3 +212,37 @@ class CookieStorage(BaseStorage):
# with the data.
self.used = True
return None
+
+
+def bisect_keep_left(a, fn):
+ """
+ Find the index of the first element from the start of the array that
+ verifies the given condition.
+ The function is applied from the start of the array to the pivot.
+ """
+ lo = 0
+ hi = len(a)
+ while lo < hi:
+ mid = (lo + hi) // 2
+ if fn(a[: mid + 1]):
+ hi = mid
+ else:
+ lo = mid + 1
+ return lo
+
+
+def bisect_keep_right(a, fn):
+ """
+ Find the index of the first element from the end of the array that verifies
+ the given condition.
+ The function is applied from the pivot to the end of array.
+ """
+ lo = 0
+ hi = len(a)
+ while lo < hi:
+ mid = (lo + hi) // 2
+ if fn(a[mid:]):
+ lo = mid + 1
+ else:
+ hi = mid
+ return lo