Skip to content

Commit 17da20e

Browse files
Small micro optimisations
1 parent f3bcdd9 commit 17da20e

File tree

1 file changed

+30
-17
lines changed

1 file changed

+30
-17
lines changed

w3lib/http.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from __future__ import annotations
22

33
from base64 import b64encode
4+
from collections import defaultdict
45
from collections.abc import Mapping, MutableMapping, Sequence
6+
from io import BytesIO
57
from typing import Any, Union, overload
68

79
from w3lib.util import to_bytes, to_unicode
@@ -44,23 +46,22 @@ def headers_raw_to_dict(headers_raw: bytes | None) -> HeadersDictOutput | None:
4446

4547
if headers_raw is None:
4648
return None
47-
headers = headers_raw.splitlines()
48-
headers_tuples = [header.split(b":", 1) for header in headers]
4949

50-
result_dict: HeadersDictOutput = {}
51-
for header_item in headers_tuples:
52-
if len(header_item) != 2:
53-
continue
50+
if not headers_raw:
51+
return {}
52+
53+
headers = iter(BytesIO(headers_raw).readline, b"")
54+
result_dict = defaultdict(list)
5455

55-
item_key = header_item[0].strip()
56-
item_value = header_item[1].strip()
56+
for header in headers:
57+
parts = header.split(b":", 1)
58+
if len(parts) != 2:
59+
continue
5760

58-
if item_key in result_dict:
59-
result_dict[item_key].append(item_value)
60-
else:
61-
result_dict[item_key] = [item_value]
61+
key, value = map(bytes.strip, parts)
62+
result_dict[key].append(value)
6263

63-
return result_dict
64+
return dict(result_dict)
6465

6566

6667
@overload
@@ -93,13 +94,25 @@ def headers_dict_to_raw(headers_dict: HeadersDictInput | None) -> bytes | None:
9394

9495
if headers_dict is None:
9596
return None
96-
raw_lines = []
97+
98+
if not headers_dict:
99+
return b""
100+
101+
parts = bytearray()
102+
97103
for key, value in headers_dict.items():
98104
if isinstance(value, bytes):
99-
raw_lines.append(b": ".join([key, value]))
105+
if parts:
106+
parts.extend(b"\r\n")
107+
parts.extend(key + b": " + value)
108+
100109
elif isinstance(value, (list, tuple)):
101-
raw_lines.extend(b": ".join([key, v]) for v in value)
102-
return b"\r\n".join(raw_lines)
110+
for v in value:
111+
if parts:
112+
parts.extend(b"\r\n")
113+
parts.extend(key + b": " + v)
114+
115+
return bytes(parts)
103116

104117

105118
def basic_auth_header(

0 commit comments

Comments
 (0)