Skip to content

Commit

Permalink
🐛 Fix parse_it when given Mapping contains bytes values/keys (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ousret authored Oct 22, 2023
1 parent 6c2fd5d commit f06abea
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
7 changes: 5 additions & 2 deletions kiss_headers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
is_content_json_object,
is_legal_header_name,
normalize_str,
transform_possible_encoded,
)

T = TypeVar("T", bound=CustomHeader, covariant=True)
Expand All @@ -31,7 +32,7 @@ def parse_it(raw_headers: Any) -> Headers:
TypeError: If passed argument cannot be parsed to extract headers from it.
"""

headers: Optional[Iterable[Tuple[str, Any]]] = None
headers: Optional[Iterable[Tuple[Union[str, bytes], Union[str, bytes]]]] = None

if isinstance(raw_headers, str):
if raw_headers.startswith("{") and raw_headers.endswith("}"):
Expand Down Expand Up @@ -71,7 +72,9 @@ def parse_it(raw_headers: Any) -> Headers:
)
)

revised_headers: List[Tuple[str, str]] = decode_partials(headers)
revised_headers: List[Tuple[str, str]] = decode_partials(
transform_possible_encoded(headers)
)

# Sometime raw content does not begin with headers. If that is the case, search for the next line.
if (
Expand Down
12 changes: 10 additions & 2 deletions kiss_headers/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Header(object):
"""

# Most common attribute that are associated with value in headers.
# Used for type hint, auto completion purpose
# Used for type hint, auto-completion purpose
charset: str
format: str
boundary: str
Expand All @@ -39,6 +39,11 @@ class Header(object):
samesite: str
domain: str
filename: str
to: str
report_to: str
endpoints: str
max_age: str
group: str

def __init__(self, name: str, content: str):
"""
Expand Down Expand Up @@ -619,6 +624,8 @@ class Headers(object):

alt_svc: Union[Header, List[Header]]

location: Union[Header, List[Header]]

age: Union[Header, List[Header]]
cache_control: Union[Header, List[Header]]
clear_site_data: Union[Header, List[Header]]
Expand Down Expand Up @@ -650,8 +657,9 @@ class Headers(object):
set_cookie: Union[Header, List[Header]]

content_disposition: Union[Header, List[Header]]

content_type: Union[Header, List[Header]]
content_range: Union[Header, List[Header]]
content_encoding: Union[Header, List[Header]]

host: Union[Header, List[Header]]
referer: Union[Header, List[Header]]
Expand Down
17 changes: 16 additions & 1 deletion kiss_headers/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from email.header import decode_header
from re import findall, search, sub
from typing import Any, Iterable, List, Optional, Set, Tuple, Type
from typing import Any, Iterable, List, Optional, Set, Tuple, Type, Union

RESERVED_KEYWORD: Set[str] = {
"and_",
Expand Down Expand Up @@ -461,3 +461,18 @@ def is_content_json_object(content: str) -> bool:
return (content.startswith("{") and content.endswith("}")) or (
content.startswith("[") and content.endswith("]")
)


def transform_possible_encoded(
headers: Iterable[Tuple[Union[str, bytes], Union[str, bytes]]]
) -> Iterable[Tuple[str, str]]:
decoded = []

for k, v in headers:
if isinstance(k, bytes):
k = k.decode("utf_8")
if isinstance(v, bytes):
v = v.decode("utf_8")
decoded.append((k, v))

return decoded
2 changes: 1 addition & 1 deletion kiss_headers/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
Expose version
"""

__version__ = "2.4.0"
__version__ = "2.4.1"
VERSION = __version__.split(".")

0 comments on commit f06abea

Please sign in to comment.