fix: TLS backends return case-insensitive response headers

CurlCffi.raw_request and Noble's _flatten_headers built Response.headers as a plain
case-sensitive dict, while aioweb's aiohttp-backed path returns a CIMultiDict -
resp.headers.get('content-type') silently returned None on TLS backends when the
server sent 'Content-Type', contradicting the "backends behave identically" claim.
Both paths now build a multidict.CIMultiDict instead.

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
2026-07-06 00:10:20 -04:00
parent b23e1d399e
commit df48d1cea3
+8 -6
View File
@@ -9,6 +9,7 @@ import logging
import math
import aiohttp
from multidict import CIMultiDict
from aioweb import Response
log = logging.getLogger(__name__)
@@ -77,13 +78,14 @@ def _noble_content(response) -> bytes:
return text.encode()
def _flatten_headers(headers) -> dict:
def _flatten_headers(headers) -> CIMultiDict:
"""flatten a Go-style map[str][]str header dict (multi-valued headers as a list)
into plain str values, joined with ", " per RFC 7230"""
return {
key: ", ".join(value) if isinstance(value, list) else value
into plain str values, joined with ", " per RFC 7230, into a case-insensitive
mapping matching aioweb's aiohttp-backed Response.headers"""
return CIMultiDict(
(key, ", ".join(value) if isinstance(value, list) else value)
for key, value in headers.items()
}
)
def _history_entries(history) -> list:
@@ -177,7 +179,7 @@ class CurlCffi:
content = response.content if response.content is not None else b""
return Response(
status_code=response.status_code,
headers=dict(response.headers),
headers=CIMultiDict(response.headers),
content=content,
url=str(response.url),
reason=getattr(response, "reason", None),