Skip to content

Commit 1998286

Browse files
committed
Normalize multiple Transfer-Encoding headers before chunked detection
1 parent 0f0b0e5 commit 1998286

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

aiohttp/http_parser.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,8 +584,11 @@ def parse_headers(
584584
encoding = enc
585585

586586
# chunking
587-
te = headers.get(hdrs.TRANSFER_ENCODING)
588-
if te is not None:
587+
te_values = headers.getall(hdrs.TRANSFER_ENCODING, ())
588+
if te_values:
589+
# RFC 9110 §5.3: Multiple header fields are equivalent to a single
590+
# comma-separated value. Normalize before determining message framing.
591+
te = ",".join(v.strip() for v in te_values)
589592
if self._is_chunked_te(te):
590593
chunked = True
591594

tests/test_http_parser.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,25 @@ def test_duplicate_singleton_header_accepted_in_lax_mode(
399399
assert len(messages) == 1
400400

401401

402+
async def test_response_te_split_headers_chunked(
403+
response: HttpResponseParser,
404+
) -> None:
405+
text = (
406+
b"HTTP/1.1 200 OK\r\n"
407+
b"Transfer-Encoding: gzip\r\n"
408+
b"Transfer-Encoding: chunked\r\n"
409+
b"\r\n"
410+
b"4\r\nWiki\r\n0\r\n\r\n"
411+
b"HTTP/1.1 204 No Content\r\n\r\n"
412+
)
413+
messages, upgrade, tail = response.feed_data(text)
414+
assert len(messages) == 2
415+
msg1, payload1 = messages[0]
416+
assert msg1.chunked
417+
assert await payload1.read() == b"Wiki"
418+
assert messages[1][0].code == 204
419+
420+
402421
def test_duplicate_host_header_rejected(parser: HttpRequestParser) -> None:
403422
text = (
404423
b"GET /admin HTTP/1.1\r\n"

0 commit comments

Comments
 (0)