Fixed #23755 -- Added support for multiple field names in the no-cache Cache-Control directive to patch_cache_control().
https://tools.ietf.org/html/rfc7234#section-5.2.2.2
This commit is contained in:
parent
2a6f45e08e
commit
ed112fadc1
|
@ -19,6 +19,7 @@ An example: i18n middleware would need to distinguish caches by the
|
|||
import hashlib
|
||||
import re
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import caches
|
||||
|
@ -53,17 +54,21 @@ def patch_cache_control(response, **kwargs):
|
|||
else:
|
||||
return (t[0].lower(), True)
|
||||
|
||||
def dictvalue(t):
|
||||
def dictvalue(*t):
|
||||
if t[1] is True:
|
||||
return t[0]
|
||||
else:
|
||||
return '%s=%s' % (t[0], t[1])
|
||||
|
||||
cc = defaultdict(set)
|
||||
if response.get('Cache-Control'):
|
||||
cc = cc_delim_re.split(response['Cache-Control'])
|
||||
cc = dict(dictitem(el) for el in cc)
|
||||
else:
|
||||
cc = {}
|
||||
for field in cc_delim_re.split(response['Cache-Control']):
|
||||
directive, value = dictitem(field)
|
||||
if directive == 'no-cache':
|
||||
# no-cache supports multiple field names.
|
||||
cc[directive].add(value)
|
||||
else:
|
||||
cc[directive] = value
|
||||
|
||||
# If there's already a max-age header but we're being asked to set a new
|
||||
# max-age, use the minimum of the two ages. In practice this happens when
|
||||
|
@ -78,8 +83,23 @@ def patch_cache_control(response, **kwargs):
|
|||
del cc['public']
|
||||
|
||||
for (k, v) in kwargs.items():
|
||||
cc[k.replace('_', '-')] = v
|
||||
cc = ', '.join(dictvalue(el) for el in cc.items())
|
||||
directive = k.replace('_', '-')
|
||||
if directive == 'no-cache':
|
||||
# no-cache supports multiple field names.
|
||||
cc[directive].add(v)
|
||||
else:
|
||||
cc[directive] = v
|
||||
|
||||
directives = []
|
||||
for directive, values in cc.items():
|
||||
if isinstance(values, set):
|
||||
if True in values:
|
||||
# True takes precedence.
|
||||
values = {True}
|
||||
directives.extend([dictvalue(directive, value) for value in values])
|
||||
else:
|
||||
directives.append(dictvalue(directive, values))
|
||||
cc = ', '.join(directives)
|
||||
response['Cache-Control'] = cc
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,11 @@ need to distinguish caches by the ``Accept-language`` header.
|
|||
* All other parameters are added with their value, after applying
|
||||
``str()`` to it.
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
|
||||
Support for multiple field names in the ``no-cache`` directive was
|
||||
added.
|
||||
|
||||
.. function:: get_max_age(response)
|
||||
|
||||
Returns the max-age from the response Cache-Control header as an integer
|
||||
|
|
|
@ -104,7 +104,10 @@ Minor features
|
|||
Cache
|
||||
~~~~~
|
||||
|
||||
* ...
|
||||
* The :func:`~django.views.decorators.cache.cache_control` decorator and
|
||||
:func:`~django.utils.cache.patch_cache_control` method now support multiple
|
||||
field names in the ``no-cache`` directive for the ``Cache-Control`` header,
|
||||
according to :rfc:`7234#section-5.2.2.2`.
|
||||
|
||||
CSRF
|
||||
~~~~
|
||||
|
|
|
@ -1277,6 +1277,7 @@ Here are some more examples:
|
|||
* ``no_transform=True``
|
||||
* ``must_revalidate=True``
|
||||
* ``stale_while_revalidate=num_seconds``
|
||||
* ``no_cache=True``
|
||||
|
||||
The full list of known directives can be found in the `IANA registry`_
|
||||
(note that not all of them apply to responses).
|
||||
|
|
|
@ -1705,6 +1705,12 @@ class CacheUtils(SimpleTestCase):
|
|||
('', {'no-cache': 'Set-Cookie'}, {'no-cache=Set-Cookie'}),
|
||||
('no-cache=Set-Cookie', {'no_cache': True}, {'no-cache'}),
|
||||
('no-cache=Set-Cookie,no-cache=Link', {'no_cache': True}, {'no-cache'}),
|
||||
('no-cache=Set-Cookie', {'no_cache': 'Link'}, {'no-cache=Set-Cookie', 'no-cache=Link'}),
|
||||
(
|
||||
'no-cache=Set-Cookie,no-cache=Link',
|
||||
{'no_cache': 'Custom'},
|
||||
{'no-cache=Set-Cookie', 'no-cache=Link', 'no-cache=Custom'},
|
||||
),
|
||||
# Test whether private/public attributes are mutually exclusive
|
||||
('private', {'private': True}, {'private'}),
|
||||
('private', {'public': True}, {'public'}),
|
||||
|
|
Loading…
Reference in New Issue