diff options
| author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
| commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
| tree | f0506b668a013d0063e5fba3dbf4863b466713ba /django/utils/http.py | |
| parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'django/utils/http.py')
| -rw-r--r-- | django/utils/http.py | 124 |
1 files changed, 69 insertions, 55 deletions
diff --git a/django/utils/http.py b/django/utils/http.py index ab90f1e377..0292713235 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -5,33 +5,42 @@ import unicodedata from binascii import Error as BinasciiError from email.utils import formatdate from urllib.parse import ( - ParseResult, SplitResult, _coerce_args, _splitnetloc, _splitparams, - scheme_chars, urlencode as original_urlencode, uses_params, + ParseResult, + SplitResult, + _coerce_args, + _splitnetloc, + _splitparams, + scheme_chars, ) +from urllib.parse import urlencode as original_urlencode +from urllib.parse import uses_params from django.utils.datastructures import MultiValueDict from django.utils.regex_helper import _lazy_re_compile # based on RFC 7232, Appendix C -ETAG_MATCH = _lazy_re_compile(r''' +ETAG_MATCH = _lazy_re_compile( + r""" \A( # start of string and capture group (?:W/)? # optional weak indicator " # opening quote [^"]* # any sequence of non-quote characters " # end quote )\Z # end of string and capture group -''', re.X) +""", + re.X, +) -MONTHS = 'jan feb mar apr may jun jul aug sep oct nov dec'.split() -__D = r'(?P<day>[0-9]{2})' -__D2 = r'(?P<day>[ 0-9][0-9])' -__M = r'(?P<mon>\w{3})' -__Y = r'(?P<year>[0-9]{4})' -__Y2 = r'(?P<year>[0-9]{2})' -__T = r'(?P<hour>[0-9]{2}):(?P<min>[0-9]{2}):(?P<sec>[0-9]{2})' -RFC1123_DATE = _lazy_re_compile(r'^\w{3}, %s %s %s %s GMT$' % (__D, __M, __Y, __T)) -RFC850_DATE = _lazy_re_compile(r'^\w{6,9}, %s-%s-%s %s GMT$' % (__D, __M, __Y2, __T)) -ASCTIME_DATE = _lazy_re_compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y)) +MONTHS = "jan feb mar apr may jun jul aug sep oct nov dec".split() +__D = r"(?P<day>[0-9]{2})" +__D2 = r"(?P<day>[ 0-9][0-9])" +__M = r"(?P<mon>\w{3})" +__Y = r"(?P<year>[0-9]{4})" +__Y2 = r"(?P<year>[0-9]{2})" +__T = r"(?P<hour>[0-9]{2}):(?P<min>[0-9]{2}):(?P<sec>[0-9]{2})" +RFC1123_DATE = _lazy_re_compile(r"^\w{3}, %s %s %s %s GMT$" % (__D, __M, __Y, __T)) +RFC850_DATE = _lazy_re_compile(r"^\w{6,9}, %s-%s-%s %s GMT$" % (__D, __M, __Y2, __T)) +ASCTIME_DATE = _lazy_re_compile(r"^\w{3} %s %s %s %s$" % (__M, __D2, __T, __Y)) RFC3986_GENDELIMS = ":/?#[]@" RFC3986_SUBDELIMS = "!$&'()*+,;=" @@ -44,7 +53,7 @@ def urlencode(query, doseq=False): """ if isinstance(query, MultiValueDict): query = query.lists() - elif hasattr(query, 'items'): + elif hasattr(query, "items"): query = query.items() query_params = [] for key, value in query: @@ -112,7 +121,7 @@ def parse_http_date(date): raise ValueError("%r is not in a valid HTTP date format" % date) try: tz = datetime.timezone.utc - year = int(m['year']) + year = int(m["year"]) if year < 100: current_year = datetime.datetime.now(tz=tz).year current_century = current_year - (current_year % 100) @@ -122,11 +131,11 @@ def parse_http_date(date): year += current_century - 100 else: year += current_century - month = MONTHS.index(m['mon'].lower()) + 1 - day = int(m['day']) - hour = int(m['hour']) - min = int(m['min']) - sec = int(m['sec']) + month = MONTHS.index(m["mon"].lower()) + 1 + day = int(m["day"]) + hour = int(m["hour"]) + min = int(m["min"]) + sec = int(m["sec"]) result = datetime.datetime(year, month, day, hour, min, sec, tzinfo=tz) return int(result.timestamp()) except Exception as exc: @@ -145,6 +154,7 @@ def parse_http_date_safe(date): # Base 36 functions: useful for generating compact URLs + def base36_to_int(s): """ Convert a base 36 string to an int. Raise ValueError if the input won't fit @@ -160,12 +170,12 @@ def base36_to_int(s): def int_to_base36(i): """Convert an integer to a base36 string.""" - char_set = '0123456789abcdefghijklmnopqrstuvwxyz' + char_set = "0123456789abcdefghijklmnopqrstuvwxyz" if i < 0: raise ValueError("Negative base36 conversion input.") if i < 36: return char_set[i] - b36 = '' + b36 = "" while i != 0: i, n = divmod(i, 36) b36 = char_set[n] + b36 @@ -177,7 +187,7 @@ def urlsafe_base64_encode(s): Encode a bytestring to a base64 string for use in URLs. Strip any trailing equal signs. """ - return base64.urlsafe_b64encode(s).rstrip(b'\n=').decode('ascii') + return base64.urlsafe_b64encode(s).rstrip(b"\n=").decode("ascii") def urlsafe_base64_decode(s): @@ -187,7 +197,7 @@ def urlsafe_base64_decode(s): """ s = s.encode() try: - return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'=')) + return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b"=")) except (LookupError, BinasciiError) as e: raise ValueError(e) @@ -198,11 +208,11 @@ def parse_etags(etag_str): defined by RFC 7232. Return a list of quoted ETags, or ['*'] if all ETags should be matched. """ - if etag_str.strip() == '*': - return ['*'] + if etag_str.strip() == "*": + return ["*"] else: # Parse each ETag individually, and return any that are valid. - etag_matches = (ETAG_MATCH.match(etag.strip()) for etag in etag_str.split(',')) + etag_matches = (ETAG_MATCH.match(etag.strip()) for etag in etag_str.split(",")) return [match[1] for match in etag_matches if match] @@ -231,8 +241,9 @@ def is_same_domain(host, pattern): pattern = pattern.lower() return ( - pattern[0] == '.' and (host.endswith(pattern) or host == pattern[1:]) or - pattern == host + pattern[0] == "." + and (host.endswith(pattern) or host == pattern[1:]) + or pattern == host ) @@ -259,14 +270,15 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False): allowed_hosts = {allowed_hosts} # Chrome treats \ completely as / in paths but it could be part of some # basic auth credentials so we need to check both URLs. - return ( - _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=require_https) and - _url_has_allowed_host_and_scheme(url.replace('\\', '/'), allowed_hosts, require_https=require_https) + return _url_has_allowed_host_and_scheme( + url, allowed_hosts, require_https=require_https + ) and _url_has_allowed_host_and_scheme( + url.replace("\\", "/"), allowed_hosts, require_https=require_https ) # Copied from urllib.parse.urlparse() but uses fixed urlsplit() function. -def _urlparse(url, scheme='', allow_fragments=True): +def _urlparse(url, scheme="", allow_fragments=True): """Parse a URL into 6 components: <scheme>://<netloc>/<path>;<params>?<query>#<fragment> Return a 6-tuple: (scheme, netloc, path, params, query, fragment). @@ -275,41 +287,42 @@ def _urlparse(url, scheme='', allow_fragments=True): url, scheme, _coerce_result = _coerce_args(url, scheme) splitresult = _urlsplit(url, scheme, allow_fragments) scheme, netloc, url, query, fragment = splitresult - if scheme in uses_params and ';' in url: + if scheme in uses_params and ";" in url: url, params = _splitparams(url) else: - params = '' + params = "" result = ParseResult(scheme, netloc, url, params, query, fragment) return _coerce_result(result) # Copied from urllib.parse.urlsplit() with # https://github.com/python/cpython/pull/661 applied. -def _urlsplit(url, scheme='', allow_fragments=True): +def _urlsplit(url, scheme="", allow_fragments=True): """Parse a URL into 5 components: <scheme>://<netloc>/<path>?<query>#<fragment> Return a 5-tuple: (scheme, netloc, path, query, fragment). Note that we don't break the components up in smaller bits (e.g. netloc is a single string) and we don't expand % escapes.""" url, scheme, _coerce_result = _coerce_args(url, scheme) - netloc = query = fragment = '' - i = url.find(':') + netloc = query = fragment = "" + i = url.find(":") if i > 0: for c in url[:i]: if c not in scheme_chars: break else: - scheme, url = url[:i].lower(), url[i + 1:] + scheme, url = url[:i].lower(), url[i + 1 :] - if url[:2] == '//': + if url[:2] == "//": netloc, url = _splitnetloc(url, 2) - if (('[' in netloc and ']' not in netloc) or - (']' in netloc and '[' not in netloc)): + if ("[" in netloc and "]" not in netloc) or ( + "]" in netloc and "[" not in netloc + ): raise ValueError("Invalid IPv6 URL") - if allow_fragments and '#' in url: - url, fragment = url.split('#', 1) - if '?' in url: - url, query = url.split('?', 1) + if allow_fragments and "#" in url: + url, fragment = url.split("#", 1) + if "?" in url: + url, query = url.split("?", 1) v = SplitResult(scheme, netloc, url, query, fragment) return _coerce_result(v) @@ -317,7 +330,7 @@ def _urlsplit(url, scheme='', allow_fragments=True): def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False): # Chrome considers any URL with more than two slashes to be absolute, but # urlparse is not so flexible. Treat any url with three slashes as unsafe. - if url.startswith('///'): + if url.startswith("///"): return False try: url_info = _urlparse(url) @@ -332,15 +345,16 @@ def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False): # Forbid URLs that start with control characters. Some browsers (like # Chrome) ignore quite a few control characters at the start of a # URL and might consider the URL as scheme relative. - if unicodedata.category(url[0])[0] == 'C': + if unicodedata.category(url[0])[0] == "C": return False scheme = url_info.scheme # Consider URLs without a scheme (e.g. //example.com/p) to be http. if not url_info.scheme and url_info.netloc: - scheme = 'http' - valid_schemes = ['https'] if require_https else ['http', 'https'] - return ((not url_info.netloc or url_info.netloc in allowed_hosts) and - (not scheme or scheme in valid_schemes)) + scheme = "http" + valid_schemes = ["https"] if require_https else ["http", "https"] + return (not url_info.netloc or url_info.netloc in allowed_hosts) and ( + not scheme or scheme in valid_schemes + ) def escape_leading_slashes(url): @@ -349,6 +363,6 @@ def escape_leading_slashes(url): escaped to prevent browsers from handling the path as schemaless and redirecting to another host. """ - if url.startswith('//'): - url = '/%2F{}'.format(url[2:]) + if url.startswith("//"): + url = "/%2F{}".format(url[2:]) return url |
