From 6805c0f99f4790f28a97d597934d0877ba81dba9 Mon Sep 17 00:00:00 2001 From: Adnan Umer Date: Wed, 14 Aug 2019 01:40:09 +0500 Subject: [PATCH] Fixed #30701 -- Updated patch_vary_headers() to handle an asterisk according to RFC 7231. --- django/utils/cache.py | 11 ++++++++--- docs/ref/utils.txt | 10 ++++++++-- docs/releases/3.0.txt | 5 +++++ tests/cache/tests.py | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/django/utils/cache.py b/django/utils/cache.py index a804604642..2b37acfd44 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -256,8 +256,9 @@ def add_never_cache_headers(response): def patch_vary_headers(response, newheaders): """ Add (or update) the "Vary" header in the given HttpResponse object. - newheaders is a list of header names that should be in "Vary". Existing - headers in "Vary" aren't removed. + newheaders is a list of header names that should be in "Vary". If headers + contains an asterisk, then "Vary" header will consist of a single asterisk + '*'. Otherwise, existing headers in "Vary" aren't removed. """ # Note that we need to keep the original order intact, because cache # implementations may rely on the order of the Vary contents in, say, @@ -270,7 +271,11 @@ def patch_vary_headers(response, newheaders): existing_headers = {header.lower() for header in vary_headers} additional_headers = [newheader for newheader in newheaders if newheader.lower() not in existing_headers] - response['Vary'] = ', '.join(vary_headers + additional_headers) + vary_headers += additional_headers + if '*' in vary_headers: + response['Vary'] = '*' + else: + response['Vary'] = ', '.join(vary_headers) def has_vary_header(response, header_query): diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 3d3dbab2fe..06136da08f 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -73,8 +73,14 @@ need to distinguish caches by the ``Accept-language`` header. .. function:: patch_vary_headers(response, newheaders) Adds (or updates) the ``Vary`` header in the given ``HttpResponse`` object. - ``newheaders`` is a list of header names that should be in ``Vary``. - Existing headers in ``Vary`` aren't removed. + ``newheaders`` is a list of header names that should be in ``Vary``. If + headers contains an asterisk, then ``Vary`` header will consist of a single + asterisk ``'*'``. Otherwise, existing headers in ``Vary`` aren't removed. + + .. versionchanged:: 3.0 + + Handling an asterisk ``'*'`` according to :rfc:`7231#section-7.1.4` was + added. .. function:: get_cache_key(request, key_prefix=None) diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt index 42f4c72495..bc9cbe3751 100644 --- a/docs/releases/3.0.txt +++ b/docs/releases/3.0.txt @@ -514,6 +514,11 @@ Miscellaneous :class:`~django.db.models.OneToOneField` ``'_id'`` attribute now unsets the corresponding field. Accessing the field afterwards will result in a query. +* :func:`~django.utils.cache.patch_vary_headers` now handles an asterisk + ``'*'`` according to :rfc:`7231#section-7.1.4`, i.e. if a list of header + field names contains an asterisk, then the ``Vary`` header will consist of a + single asterisk ``'*'``. + .. _deprecated-features-3.0: Features deprecated in 3.0 diff --git a/tests/cache/tests.py b/tests/cache/tests.py index ced86fc8f6..871b1498aa 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -1625,6 +1625,8 @@ class CacheUtils(SimpleTestCase): (None, ('Accept-Encoding', 'COOKIE'), 'Accept-Encoding, COOKIE'), ('Cookie, Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'), ('Cookie , Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'), + ('*', ('Accept-Language', 'Cookie'), '*'), + ('Accept-Language, Cookie', ('*',), '*'), ) for initial_vary, newheaders, resulting_vary in headers: with self.subTest(initial_vary=initial_vary, newheaders=newheaders):