测试gitnore
This commit is contained in:
@@ -23,13 +23,15 @@ from collections import defaultdict
|
||||
from django.conf import settings
|
||||
from django.core.cache import caches
|
||||
from django.http import HttpResponse, HttpResponseNotModified
|
||||
from django.utils.http import http_date, parse_etags, parse_http_date_safe, quote_etag
|
||||
from django.utils.http import (
|
||||
http_date, parse_etags, parse_http_date_safe, quote_etag,
|
||||
)
|
||||
from django.utils.log import log_response
|
||||
from django.utils.regex_helper import _lazy_re_compile
|
||||
from django.utils.timezone import get_current_timezone_name
|
||||
from django.utils.translation import get_language
|
||||
|
||||
cc_delim_re = _lazy_re_compile(r"\s*,\s*")
|
||||
cc_delim_re = _lazy_re_compile(r'\s*,\s*')
|
||||
|
||||
|
||||
def patch_cache_control(response, **kwargs):
|
||||
@@ -44,9 +46,8 @@ def patch_cache_control(response, **kwargs):
|
||||
* All other parameters are added with their value, after applying
|
||||
str() to it.
|
||||
"""
|
||||
|
||||
def dictitem(s):
|
||||
t = s.split("=", 1)
|
||||
t = s.split('=', 1)
|
||||
if len(t) > 1:
|
||||
return (t[0].lower(), t[1])
|
||||
else:
|
||||
@@ -56,13 +57,13 @@ def patch_cache_control(response, **kwargs):
|
||||
if t[1] is True:
|
||||
return t[0]
|
||||
else:
|
||||
return "%s=%s" % (t[0], t[1])
|
||||
return '%s=%s' % (t[0], t[1])
|
||||
|
||||
cc = defaultdict(set)
|
||||
if response.get("Cache-Control"):
|
||||
for field in cc_delim_re.split(response.headers["Cache-Control"]):
|
||||
if response.get('Cache-Control'):
|
||||
for field in cc_delim_re.split(response.headers['Cache-Control']):
|
||||
directive, value = dictitem(field)
|
||||
if directive == "no-cache":
|
||||
if directive == 'no-cache':
|
||||
# no-cache supports multiple field names.
|
||||
cc[directive].add(value)
|
||||
else:
|
||||
@@ -71,18 +72,18 @@ def patch_cache_control(response, **kwargs):
|
||||
# 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
|
||||
# a decorator and a piece of middleware both operate on a given view.
|
||||
if "max-age" in cc and "max_age" in kwargs:
|
||||
kwargs["max_age"] = min(int(cc["max-age"]), kwargs["max_age"])
|
||||
if 'max-age' in cc and 'max_age' in kwargs:
|
||||
kwargs['max_age'] = min(int(cc['max-age']), kwargs['max_age'])
|
||||
|
||||
# Allow overriding private caching and vice versa
|
||||
if "private" in cc and "public" in kwargs:
|
||||
del cc["private"]
|
||||
elif "public" in cc and "private" in kwargs:
|
||||
del cc["public"]
|
||||
if 'private' in cc and 'public' in kwargs:
|
||||
del cc['private']
|
||||
elif 'public' in cc and 'private' in kwargs:
|
||||
del cc['public']
|
||||
|
||||
for (k, v) in kwargs.items():
|
||||
directive = k.replace("_", "-")
|
||||
if directive == "no-cache":
|
||||
directive = k.replace('_', '-')
|
||||
if directive == 'no-cache':
|
||||
# no-cache supports multiple field names.
|
||||
cc[directive].add(v)
|
||||
else:
|
||||
@@ -97,8 +98,8 @@ def patch_cache_control(response, **kwargs):
|
||||
directives.extend([dictvalue(directive, value) for value in values])
|
||||
else:
|
||||
directives.append(dictvalue(directive, values))
|
||||
cc = ", ".join(directives)
|
||||
response.headers["Cache-Control"] = cc
|
||||
cc = ', '.join(directives)
|
||||
response.headers['Cache-Control'] = cc
|
||||
|
||||
|
||||
def get_max_age(response):
|
||||
@@ -106,28 +107,25 @@ def get_max_age(response):
|
||||
Return the max-age from the response Cache-Control header as an integer,
|
||||
or None if it wasn't found or wasn't an integer.
|
||||
"""
|
||||
if not response.has_header("Cache-Control"):
|
||||
if not response.has_header('Cache-Control'):
|
||||
return
|
||||
cc = dict(
|
||||
_to_tuple(el) for el in cc_delim_re.split(response.headers["Cache-Control"])
|
||||
)
|
||||
cc = dict(_to_tuple(el) for el in cc_delim_re.split(response.headers['Cache-Control']))
|
||||
try:
|
||||
return int(cc["max-age"])
|
||||
return int(cc['max-age'])
|
||||
except (ValueError, TypeError, KeyError):
|
||||
pass
|
||||
|
||||
|
||||
def set_response_etag(response):
|
||||
if not response.streaming and response.content:
|
||||
response.headers["ETag"] = quote_etag(hashlib.md5(response.content).hexdigest())
|
||||
response.headers['ETag'] = quote_etag(hashlib.md5(response.content).hexdigest())
|
||||
return response
|
||||
|
||||
|
||||
def _precondition_failed(request):
|
||||
response = HttpResponse(status=412)
|
||||
log_response(
|
||||
"Precondition Failed: %s",
|
||||
request.path,
|
||||
'Precondition Failed: %s', request.path,
|
||||
response=response,
|
||||
request=request,
|
||||
)
|
||||
@@ -139,15 +137,7 @@ def _not_modified(request, response=None):
|
||||
if response:
|
||||
# Preserve the headers required by Section 4.1 of RFC 7232, as well as
|
||||
# Last-Modified.
|
||||
for header in (
|
||||
"Cache-Control",
|
||||
"Content-Location",
|
||||
"Date",
|
||||
"ETag",
|
||||
"Expires",
|
||||
"Last-Modified",
|
||||
"Vary",
|
||||
):
|
||||
for header in ('Cache-Control', 'Content-Location', 'Date', 'ETag', 'Expires', 'Last-Modified', 'Vary'):
|
||||
if header in response:
|
||||
new_response.headers[header] = response.headers[header]
|
||||
|
||||
@@ -166,13 +156,11 @@ def get_conditional_response(request, etag=None, last_modified=None, response=No
|
||||
return response
|
||||
|
||||
# Get HTTP request headers.
|
||||
if_match_etags = parse_etags(request.META.get("HTTP_IF_MATCH", ""))
|
||||
if_unmodified_since = request.META.get("HTTP_IF_UNMODIFIED_SINCE")
|
||||
if_unmodified_since = if_unmodified_since and parse_http_date_safe(
|
||||
if_unmodified_since
|
||||
)
|
||||
if_none_match_etags = parse_etags(request.META.get("HTTP_IF_NONE_MATCH", ""))
|
||||
if_modified_since = request.META.get("HTTP_IF_MODIFIED_SINCE")
|
||||
if_match_etags = parse_etags(request.META.get('HTTP_IF_MATCH', ''))
|
||||
if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
|
||||
if_unmodified_since = if_unmodified_since and parse_http_date_safe(if_unmodified_since)
|
||||
if_none_match_etags = parse_etags(request.META.get('HTTP_IF_NONE_MATCH', ''))
|
||||
if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
|
||||
if_modified_since = if_modified_since and parse_http_date_safe(if_modified_since)
|
||||
|
||||
# Step 1 of section 6 of RFC 7232: Test the If-Match precondition.
|
||||
@@ -180,26 +168,23 @@ def get_conditional_response(request, etag=None, last_modified=None, response=No
|
||||
return _precondition_failed(request)
|
||||
|
||||
# Step 2: Test the If-Unmodified-Since precondition.
|
||||
if (
|
||||
not if_match_etags
|
||||
and if_unmodified_since
|
||||
and not _if_unmodified_since_passes(last_modified, if_unmodified_since)
|
||||
):
|
||||
if (not if_match_etags and if_unmodified_since and
|
||||
not _if_unmodified_since_passes(last_modified, if_unmodified_since)):
|
||||
return _precondition_failed(request)
|
||||
|
||||
# Step 3: Test the If-None-Match precondition.
|
||||
if if_none_match_etags and not _if_none_match_passes(etag, if_none_match_etags):
|
||||
if request.method in ("GET", "HEAD"):
|
||||
if request.method in ('GET', 'HEAD'):
|
||||
return _not_modified(request, response)
|
||||
else:
|
||||
return _precondition_failed(request)
|
||||
|
||||
# Step 4: Test the If-Modified-Since precondition.
|
||||
if (
|
||||
not if_none_match_etags
|
||||
and if_modified_since
|
||||
and not _if_modified_since_passes(last_modified, if_modified_since)
|
||||
and request.method in ("GET", "HEAD")
|
||||
not if_none_match_etags and
|
||||
if_modified_since and
|
||||
not _if_modified_since_passes(last_modified, if_modified_since) and
|
||||
request.method in ('GET', 'HEAD')
|
||||
):
|
||||
return _not_modified(request, response)
|
||||
|
||||
@@ -215,12 +200,12 @@ def _if_match_passes(target_etag, etags):
|
||||
if not target_etag:
|
||||
# If there isn't an ETag, then there can't be a match.
|
||||
return False
|
||||
elif etags == ["*"]:
|
||||
elif etags == ['*']:
|
||||
# The existence of an ETag means that there is "a current
|
||||
# representation for the target resource", even if the ETag is weak,
|
||||
# so there is a match to '*'.
|
||||
return True
|
||||
elif target_etag.startswith("W/"):
|
||||
elif target_etag.startswith('W/'):
|
||||
# A weak ETag can never strongly match another ETag.
|
||||
return False
|
||||
else:
|
||||
@@ -244,15 +229,15 @@ def _if_none_match_passes(target_etag, etags):
|
||||
if not target_etag:
|
||||
# If there isn't an ETag, then there isn't a match.
|
||||
return True
|
||||
elif etags == ["*"]:
|
||||
elif etags == ['*']:
|
||||
# The existence of an ETag means that there is "a current
|
||||
# representation for the target resource", so there is a match to '*'.
|
||||
return False
|
||||
else:
|
||||
# The comparison should be weak, so look for a match after stripping
|
||||
# off any weak indicators.
|
||||
target_etag = target_etag.strip("W/")
|
||||
etags = (etag.strip("W/") for etag in etags)
|
||||
target_etag = target_etag.strip('W/')
|
||||
etags = (etag.strip('W/') for etag in etags)
|
||||
return target_etag not in etags
|
||||
|
||||
|
||||
@@ -277,8 +262,8 @@ def patch_response_headers(response, cache_timeout=None):
|
||||
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
|
||||
if cache_timeout < 0:
|
||||
cache_timeout = 0 # Can't have max-age negative
|
||||
if not response.has_header("Expires"):
|
||||
response.headers["Expires"] = http_date(time.time() + cache_timeout)
|
||||
if not response.has_header('Expires'):
|
||||
response.headers['Expires'] = http_date(time.time() + cache_timeout)
|
||||
patch_cache_control(response, max_age=cache_timeout)
|
||||
|
||||
|
||||
@@ -287,9 +272,7 @@ def add_never_cache_headers(response):
|
||||
Add headers to a response to indicate that a page should never be cached.
|
||||
"""
|
||||
patch_response_headers(response, cache_timeout=-1)
|
||||
patch_cache_control(
|
||||
response, no_cache=True, no_store=True, must_revalidate=True, private=True
|
||||
)
|
||||
patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True, private=True)
|
||||
|
||||
|
||||
def patch_vary_headers(response, newheaders):
|
||||
@@ -302,31 +285,28 @@ def patch_vary_headers(response, newheaders):
|
||||
# Note that we need to keep the original order intact, because cache
|
||||
# implementations may rely on the order of the Vary contents in, say,
|
||||
# computing an MD5 hash.
|
||||
if response.has_header("Vary"):
|
||||
vary_headers = cc_delim_re.split(response.headers["Vary"])
|
||||
if response.has_header('Vary'):
|
||||
vary_headers = cc_delim_re.split(response.headers['Vary'])
|
||||
else:
|
||||
vary_headers = []
|
||||
# Use .lower() here so we treat headers as case-insensitive.
|
||||
existing_headers = {header.lower() for header in vary_headers}
|
||||
additional_headers = [
|
||||
newheader
|
||||
for newheader in newheaders
|
||||
if newheader.lower() not in existing_headers
|
||||
]
|
||||
additional_headers = [newheader for newheader in newheaders
|
||||
if newheader.lower() not in existing_headers]
|
||||
vary_headers += additional_headers
|
||||
if "*" in vary_headers:
|
||||
response.headers["Vary"] = "*"
|
||||
if '*' in vary_headers:
|
||||
response.headers['Vary'] = '*'
|
||||
else:
|
||||
response.headers["Vary"] = ", ".join(vary_headers)
|
||||
response.headers['Vary'] = ', '.join(vary_headers)
|
||||
|
||||
|
||||
def has_vary_header(response, header_query):
|
||||
"""
|
||||
Check to see if the response has a given header name in its Vary header.
|
||||
"""
|
||||
if not response.has_header("Vary"):
|
||||
if not response.has_header('Vary'):
|
||||
return False
|
||||
vary_headers = cc_delim_re.split(response.headers["Vary"])
|
||||
vary_headers = cc_delim_re.split(response.headers['Vary'])
|
||||
existing_headers = {header.lower() for header in vary_headers}
|
||||
return header_query.lower() in existing_headers
|
||||
|
||||
@@ -337,9 +317,9 @@ def _i18n_cache_key_suffix(request, cache_key):
|
||||
# first check if LocaleMiddleware or another middleware added
|
||||
# LANGUAGE_CODE to request, then fall back to the active language
|
||||
# which in turn can also fall back to settings.LANGUAGE_CODE
|
||||
cache_key += ".%s" % getattr(request, "LANGUAGE_CODE", get_language())
|
||||
cache_key += '.%s' % getattr(request, 'LANGUAGE_CODE', get_language())
|
||||
if settings.USE_TZ:
|
||||
cache_key += ".%s" % get_current_timezone_name()
|
||||
cache_key += '.%s' % get_current_timezone_name()
|
||||
return cache_key
|
||||
|
||||
|
||||
@@ -350,27 +330,21 @@ def _generate_cache_key(request, method, headerlist, key_prefix):
|
||||
value = request.META.get(header)
|
||||
if value is not None:
|
||||
ctx.update(value.encode())
|
||||
url = hashlib.md5(request.build_absolute_uri().encode("ascii"))
|
||||
cache_key = "views.decorators.cache.cache_page.%s.%s.%s.%s" % (
|
||||
key_prefix,
|
||||
method,
|
||||
url.hexdigest(),
|
||||
ctx.hexdigest(),
|
||||
)
|
||||
url = hashlib.md5(request.build_absolute_uri().encode('ascii'))
|
||||
cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % (
|
||||
key_prefix, method, url.hexdigest(), ctx.hexdigest())
|
||||
return _i18n_cache_key_suffix(request, cache_key)
|
||||
|
||||
|
||||
def _generate_cache_header_key(key_prefix, request):
|
||||
"""Return a cache key for the header cache."""
|
||||
url = hashlib.md5(request.build_absolute_uri().encode("ascii"))
|
||||
cache_key = "views.decorators.cache.cache_header.%s.%s" % (
|
||||
key_prefix,
|
||||
url.hexdigest(),
|
||||
)
|
||||
url = hashlib.md5(request.build_absolute_uri().encode('ascii'))
|
||||
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
|
||||
key_prefix, url.hexdigest())
|
||||
return _i18n_cache_key_suffix(request, cache_key)
|
||||
|
||||
|
||||
def get_cache_key(request, key_prefix=None, method="GET", cache=None):
|
||||
def get_cache_key(request, key_prefix=None, method='GET', cache=None):
|
||||
"""
|
||||
Return a cache key based on the request URL and query. It can be used
|
||||
in the request phase because it pulls the list of headers to take into
|
||||
@@ -412,17 +386,17 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cach
|
||||
cache_key = _generate_cache_header_key(key_prefix, request)
|
||||
if cache is None:
|
||||
cache = caches[settings.CACHE_MIDDLEWARE_ALIAS]
|
||||
if response.has_header("Vary"):
|
||||
if response.has_header('Vary'):
|
||||
is_accept_language_redundant = settings.USE_I18N
|
||||
# If i18n is used, the generated cache key will be suffixed with the
|
||||
# current locale. Adding the raw value of Accept-Language is redundant
|
||||
# in that case and would result in storing the same content under
|
||||
# multiple keys in the cache. See #18191 for details.
|
||||
headerlist = []
|
||||
for header in cc_delim_re.split(response.headers["Vary"]):
|
||||
header = header.upper().replace("-", "_")
|
||||
if header != "ACCEPT_LANGUAGE" or not is_accept_language_redundant:
|
||||
headerlist.append("HTTP_" + header)
|
||||
for header in cc_delim_re.split(response.headers['Vary']):
|
||||
header = header.upper().replace('-', '_')
|
||||
if header != 'ACCEPT_LANGUAGE' or not is_accept_language_redundant:
|
||||
headerlist.append('HTTP_' + header)
|
||||
headerlist.sort()
|
||||
cache.set(cache_key, headerlist, cache_timeout)
|
||||
return _generate_cache_key(request, request.method, headerlist, key_prefix)
|
||||
@@ -434,7 +408,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cach
|
||||
|
||||
|
||||
def _to_tuple(s):
|
||||
t = s.split("=", 1)
|
||||
t = s.split('=', 1)
|
||||
if len(t) == 2:
|
||||
return t[0].lower(), t[1]
|
||||
return t[0].lower(), True
|
||||
|
||||
Reference in New Issue
Block a user