Describe the bug
parse_content_disposition (in aiohttp/multipart.py) does not strip whitespace from the disposition type (the part before the first ;) before checking whether it is a valid token. RFC 7230 permits optional whitespace (OWS) around separators, so a header value like form-data ; name="field" (space before the semicolon) is technically conforming—yet aiohttp rejects it entirely, emitting a BadContentDispositionHeader warning and returning (None, {}) instead of ('form-data', {'name': 'field'}).
To Reproduce
import warnings
from aiohttp.multipart import parse_content_disposition, BadContentDispositionHeader
# Space before the first semicolon — valid per RFC 7230 BWS rules
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
disptype, params = parse_content_disposition('form-data ; name="field"')
print(disptype, params) # None {} ← bug; should be ('form-data', {'name': 'field'})
print(w[0].category.__name__ if w else 'no warning') # BadContentDispositionHeader
Expected behavior
Trailing (and leading) whitespace on the disposition type is stripped before validation, consistent with how parameter keys are already handled (key = key.lower().strip()):
disptype='form-data' params={'name': 'field'}
Root cause
In parse_content_disposition:
disptype, *parts = header.split(";")
if not is_token(disptype): # ← disptype not stripped; 'form-data ' fails is_token
warnings.warn(BadContentDispositionHeader(header))
return None, {}
The fix is a single line: disptype = disptype.strip() before the is_token check.
aiohttp Version
master (7987bd2)
Python Version
3.12
Related component
multipart / content-disposition parsing
Code of Conduct
Describe the bug
parse_content_disposition(inaiohttp/multipart.py) does not strip whitespace from the disposition type (the part before the first;) before checking whether it is a valid token. RFC 7230 permits optional whitespace (OWS) around separators, so a header value likeform-data ; name="field"(space before the semicolon) is technically conforming—yet aiohttp rejects it entirely, emitting aBadContentDispositionHeaderwarning and returning(None, {})instead of('form-data', {'name': 'field'}).To Reproduce
Expected behavior
Trailing (and leading) whitespace on the disposition type is stripped before validation, consistent with how parameter keys are already handled (
key = key.lower().strip()):Root cause
In
parse_content_disposition:The fix is a single line:
disptype = disptype.strip()before theis_tokencheck.aiohttp Version
master (7987bd2)
Python Version
3.12
Related component
multipart / content-disposition parsing
Code of Conduct