Summary
When a server returns multiple HTTP headers with the same name, only the last value is preserved. According to RFC 7230, duplicate headers should be merged into a comma-separated string (e.g., "v1, v2"), but instead previous values are completely overwritten.
Environment
- pyodide-http version: latest
- Pyodide version: (as used in Langchain sandbox)
Reproduction
Server Response (multiple headers with same name)
HTTP/1.1 200 OK
X-Custom-Header: value1
X-Custom-Header: value2
X-Custom-Header: value3
Set-Cookie: cookie1=abc; Path=/
Set-Cookie: cookie2=def; Path=/
Set-Cookie: cookie3=xyz; Path=/
Content-Length: 0
Python Code
import requests
response = requests.get("https://example.com/api/endpoint")
# Test with custom header
print(response.headers.get("X-Custom-Header"))
# Test with Set-Cookie
print(response.headers.get("Set-Cookie"))
Expected Output (per RFC 7230)
Duplicate headers should be merged with comma separator:
response.headers.get("X-Custom-Header")
# "value1, value2, value3"
response.headers.get("Set-Cookie")
# "cookie1=abc; Path=/, cookie2=def; Path=/, cookie3=xyz; Path=/"
Actual Output
Only the last header value is preserved:
response.headers.get("X-Custom-Header")
# "value3" ❌ Only last value!
response.headers.get("Set-Cookie")
# "cookie3=xyz; Path=/" ❌ Only last cookie!
Expected Behavior (per RFC 7230)
RFC 7230 Section 3.2.2 states:
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.
Suggested Fix
Option 1: Merge duplicate headers with comma separator
headers = {}
for name, value in js_headers:
if name in headers:
headers[name] = headers[name] + ", " + value # ✅ Merge with comma
else:
headers[name] = value
Option 2: Use urllib3's HTTPHeaderDict
from urllib3._collections import HTTPHeaderDict
headers = HTTPHeaderDict()
for name, value in js_headers:
headers.add(name, value) # ✅ Supports getlist() for duplicates
Option 3: Special handling for Set-Cookie
For Set-Cookie specifically, modern browsers provide headers.getSetCookie():
// JavaScript - returns array of all Set-Cookie values
const setCookies = response.headers.getSetCookie();
This could be used to properly populate response.cookies in Python.
Impact
This bug breaks compatibility with:
-
Any API returning multiple headers with the same name
-
Authentication systems returning multiple Set-Cookie headers, including:
- OpenText ALM (Application Lifecycle Management)
- Enterprise SSO systems
- OAuth implementations
- Any service using multiple session/auth cookies
-
APIs using multiple values for:
Link headers (pagination)
WWW-Authenticate headers
- Custom headers with multiple values
Current Workaround
There is no workaround from within the Pyodide environment. For cookie-based authentication, users must:
- Authenticate externally (using local Python or other tools)
- Manually extract all cookies
- Pass pre-authenticated cookies as hardcoded values
This is impractical for production applications.
Test Case
def test_duplicate_headers_merged():
"""Duplicate headers should be merged per RFC 7230."""
import requests
# Assuming a test endpoint that returns duplicate headers
response = requests.get("https://httpbin.org/response-headers", params={
"X-Test": ["value1", "value2"]
})
# Should be comma-merged, not overwritten
assert response.headers.get("X-Test") == "value1, value2"
References
Summary
When a server returns multiple HTTP headers with the same name, only the last value is preserved. According to RFC 7230, duplicate headers should be merged into a comma-separated string (e.g.,
"v1, v2"), but instead previous values are completely overwritten.Environment
Reproduction
Server Response (multiple headers with same name)
Python Code
Expected Output (per RFC 7230)
Duplicate headers should be merged with comma separator:
Actual Output
Only the last header value is preserved:
Expected Behavior (per RFC 7230)
RFC 7230 Section 3.2.2 states:
Suggested Fix
Option 1: Merge duplicate headers with comma separator
Option 2: Use urllib3's HTTPHeaderDict
Option 3: Special handling for Set-Cookie
For
Set-Cookiespecifically, modern browsers provideheaders.getSetCookie():This could be used to properly populate
response.cookiesin Python.Impact
This bug breaks compatibility with:
Any API returning multiple headers with the same name
Authentication systems returning multiple
Set-Cookieheaders, including:APIs using multiple values for:
Linkheaders (pagination)WWW-AuthenticateheadersCurrent Workaround
There is no workaround from within the Pyodide environment. For cookie-based authentication, users must:
This is impractical for production applications.
Test Case
References