Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/w3lib/http.py: 24%
34 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
1from base64 import b64encode
2from typing import Any, List, MutableMapping, Optional, AnyStr, Sequence, Union, Mapping
3from w3lib.util import to_bytes, to_unicode
5HeadersDictInput = Mapping[bytes, Union[Any, Sequence[bytes]]]
6HeadersDictOutput = MutableMapping[bytes, List[bytes]]
9def headers_raw_to_dict(headers_raw: Optional[bytes]) -> Optional[HeadersDictOutput]:
10 r"""
11 Convert raw headers (single multi-line bytestring)
12 to a dictionary.
14 For example:
16 >>> import w3lib.http
17 >>> w3lib.http.headers_raw_to_dict(b"Content-type: text/html\n\rAccept: gzip\n\n") # doctest: +SKIP
18 {'Content-type': ['text/html'], 'Accept': ['gzip']}
20 Incorrect input:
22 >>> w3lib.http.headers_raw_to_dict(b"Content-typt gzip\n\n")
23 {}
24 >>>
26 Argument is ``None`` (return ``None``):
28 >>> w3lib.http.headers_raw_to_dict(None)
29 >>>
31 """
33 if headers_raw is None:
34 return None
35 headers = headers_raw.splitlines()
36 headers_tuples = [header.split(b":", 1) for header in headers]
38 result_dict: HeadersDictOutput = {}
39 for header_item in headers_tuples:
40 if not len(header_item) == 2:
41 continue
43 item_key = header_item[0].strip()
44 item_value = header_item[1].strip()
46 if item_key in result_dict:
47 result_dict[item_key].append(item_value)
48 else:
49 result_dict[item_key] = [item_value]
51 return result_dict
54def headers_dict_to_raw(headers_dict: Optional[HeadersDictInput]) -> Optional[bytes]:
55 r"""
56 Returns a raw HTTP headers representation of headers
58 For example:
60 >>> import w3lib.http
61 >>> w3lib.http.headers_dict_to_raw({b'Content-type': b'text/html', b'Accept': b'gzip'}) # doctest: +SKIP
62 'Content-type: text/html\\r\\nAccept: gzip'
63 >>>
65 Note that keys and values must be bytes.
67 Argument is ``None`` (returns ``None``):
69 >>> w3lib.http.headers_dict_to_raw(None)
70 >>>
72 """
74 if headers_dict is None:
75 return None
76 raw_lines = []
77 for key, value in headers_dict.items():
78 if isinstance(value, bytes):
79 raw_lines.append(b": ".join([key, value]))
80 elif isinstance(value, (list, tuple)):
81 for v in value:
82 raw_lines.append(b": ".join([key, v]))
83 return b"\r\n".join(raw_lines)
86def basic_auth_header(
87 username: AnyStr, password: AnyStr, encoding: str = "ISO-8859-1"
88) -> bytes:
89 """
90 Return an `Authorization` header field value for `HTTP Basic Access Authentication (RFC 2617)`_
92 >>> import w3lib.http
93 >>> w3lib.http.basic_auth_header('someuser', 'somepass')
94 'Basic c29tZXVzZXI6c29tZXBhc3M='
96 .. _HTTP Basic Access Authentication (RFC 2617): http://www.ietf.org/rfc/rfc2617.txt
98 """
100 auth = f"{to_unicode(username)}:{to_unicode(password)}"
101 # XXX: RFC 2617 doesn't define encoding, but ISO-8859-1
102 # seems to be the most widely used encoding here. See also:
103 # http://greenbytes.de/tech/webdav/draft-ietf-httpauth-basicauth-enc-latest.html
104 return b"Basic " + b64encode(to_bytes(auth, encoding=encoding))