from ._urls import URL
from ._utils import (
is_known_encoding,
- normalize_header_key,
- normalize_header_value,
obfuscate_sensitive_headers,
parse_content_type_charset,
parse_header_links,
__all__ = ["Cookies", "Headers", "Request", "Response"]
+def _normalize_header_key(key: str | bytes, encoding: str | None = None) -> bytes:
+ """
+ Coerce str/bytes into a strictly byte-wise HTTP header key.
+ """
+ return key if isinstance(key, bytes) else key.encode(encoding or "ascii")
+
+
+def _normalize_header_value(value: str | bytes, encoding: str | None = None) -> bytes:
+ """
+ Coerce str/bytes into a strictly byte-wise HTTP header value.
+ """
+ if isinstance(value, bytes):
+ return value
+ if not isinstance(value, str):
+ raise TypeError(f"Header value must be str or bytes, not {type(value)}")
+ return value.encode(encoding or "ascii")
+
+
class Headers(typing.MutableMapping[str, str]):
"""
HTTP headers, as a case-insensitive multi-dict.
headers: HeaderTypes | None = None,
encoding: str | None = None,
) -> None:
- if headers is None:
- self._list = [] # type: typing.List[typing.Tuple[bytes, bytes, bytes]]
- elif isinstance(headers, Headers):
+ self._list = [] # type: typing.List[typing.Tuple[bytes, bytes, bytes]]
+
+ if isinstance(headers, Headers):
self._list = list(headers._list)
elif isinstance(headers, Mapping):
- self._list = [
- (
- normalize_header_key(k, lower=False, encoding=encoding),
- normalize_header_key(k, lower=True, encoding=encoding),
- normalize_header_value(v, encoding),
- )
- for k, v in headers.items()
- ]
- else:
- self._list = [
- (
- normalize_header_key(k, lower=False, encoding=encoding),
- normalize_header_key(k, lower=True, encoding=encoding),
- normalize_header_value(v, encoding),
- )
- for k, v in headers
- ]
+ for k, v in headers.items():
+ bytes_key = _normalize_header_key(k, encoding)
+ bytes_value = _normalize_header_value(v, encoding)
+ self._list.append((bytes_key, bytes_key.lower(), bytes_value))
+ elif headers is not None:
+ for k, v in headers:
+ bytes_key = _normalize_header_key(k, encoding)
+ bytes_value = _normalize_header_value(v, encoding)
+ self._list.append((bytes_key, bytes_key.lower(), bytes_value))
self._encoding = encoding
)
-def normalize_header_key(
- value: str | bytes,
- lower: bool,
- encoding: str | None = None,
-) -> bytes:
- """
- Coerce str/bytes into a strictly byte-wise HTTP header key.
- """
- if isinstance(value, bytes):
- bytes_value = value
- else:
- bytes_value = value.encode(encoding or "ascii")
-
- return bytes_value.lower() if lower else bytes_value
-
-
-def normalize_header_value(value: str | bytes, encoding: str | None = None) -> bytes:
- """
- Coerce str/bytes into a strictly byte-wise HTTP header value.
- """
- if isinstance(value, bytes):
- return value
- if not isinstance(value, str):
- raise TypeError(f"Header value must be str or bytes, not {type(value)}")
- return value.encode(encoding or "ascii")
-
-
def primitive_value_to_str(value: PrimitiveData) -> str:
"""
Coerce a primitive data type into a string value.