Fixed #30701 -- Updated patch_vary_headers() to handle an asterisk according to RFC 7231.

This commit is contained in:
Adnan Umer 2019-08-14 01:40:09 +05:00 committed by Mariusz Felisiak
parent 7da6a28a44
commit 6805c0f99f
4 changed files with 23 additions and 5 deletions

View File

@ -256,8 +256,9 @@ def add_never_cache_headers(response):
def patch_vary_headers(response, newheaders): def patch_vary_headers(response, newheaders):
""" """
Add (or update) the "Vary" header in the given HttpResponse object. Add (or update) the "Vary" header in the given HttpResponse object.
newheaders is a list of header names that should be in "Vary". Existing newheaders is a list of header names that should be in "Vary". If headers
headers in "Vary" aren't removed. 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 # Note that we need to keep the original order intact, because cache
# implementations may rely on the order of the Vary contents in, say, # 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} existing_headers = {header.lower() for header in vary_headers}
additional_headers = [newheader for newheader in newheaders additional_headers = [newheader for newheader in newheaders
if newheader.lower() not in existing_headers] 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): def has_vary_header(response, header_query):

View File

@ -73,8 +73,14 @@ need to distinguish caches by the ``Accept-language`` header.
.. function:: patch_vary_headers(response, newheaders) .. function:: patch_vary_headers(response, newheaders)
Adds (or updates) the ``Vary`` header in the given ``HttpResponse`` object. Adds (or updates) the ``Vary`` header in the given ``HttpResponse`` object.
``newheaders`` is a list of header names that should be in ``Vary``. ``newheaders`` is a list of header names that should be in ``Vary``. If
Existing headers in ``Vary`` aren't removed. 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) .. function:: get_cache_key(request, key_prefix=None)

View File

@ -514,6 +514,11 @@ Miscellaneous
:class:`~django.db.models.OneToOneField` ``'_id'`` attribute now unsets the :class:`~django.db.models.OneToOneField` ``'_id'`` attribute now unsets the
corresponding field. Accessing the field afterwards will result in a query. 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: .. _deprecated-features-3.0:
Features deprecated in 3.0 Features deprecated in 3.0

View File

@ -1625,6 +1625,8 @@ class CacheUtils(SimpleTestCase):
(None, ('Accept-Encoding', 'COOKIE'), 'Accept-Encoding, COOKIE'), (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'),
('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: for initial_vary, newheaders, resulting_vary in headers:
with self.subTest(initial_vary=initial_vary, newheaders=newheaders): with self.subTest(initial_vary=initial_vary, newheaders=newheaders):