Summary
composio/utils/mimetypes.py has two functions that together form the file/MIME utility, and they disagree on case handling.
get_extension_from_mime_type() is deliberately case-insensitive: it lowercases its input and has a test_is_case_insensitive covering it.
guess() looks up Path(file).suffix against the lowercase _types table without normalizing case:
def guess(file: t.Union[str, Path]) -> str:
return _types.get(Path(file).suffix, _default)
so an uppercase suffix misses the table:
guess("photo.PNG") # -> "application/octet-stream", not "image/png"
guess("report.PDF") # -> "application/octet-stream", not "application/pdf"
There's a test_extension_lookup_is_case_sensitive documenting this today, so I wanted to raise it rather than just change it. But it looks unintentional:
- it's inconsistent with the sibling
get_extension_from_mime_type, which is case-insensitive;
- the stdlib
mimetypes.guess_type is also case-insensitive on the extension.
Impact
guess() feeds the mimetype field when uploading files (core/models/_files.py):
mimetype = mimetypes.guess(file=file)
Uppercase extensions are common in practice (phone cameras, scanners, Windows), so those uploads currently get application/octet-stream instead of the correct content type.
Suggested fix
Normalize the suffix before the lookup:
return _types.get(Path(file).suffix.lower(), _default)
and update test_extension_lookup_is_case_sensitive to assert the case-insensitive result. Happy to open the PR if you agree guess() should be case-insensitive like its sibling.
Summary
composio/utils/mimetypes.pyhas two functions that together form the file/MIME utility, and they disagree on case handling.get_extension_from_mime_type()is deliberately case-insensitive: it lowercases its input and has atest_is_case_insensitivecovering it.guess()looks upPath(file).suffixagainst the lowercase_typestable without normalizing case:so an uppercase suffix misses the table:
There's a
test_extension_lookup_is_case_sensitivedocumenting this today, so I wanted to raise it rather than just change it. But it looks unintentional:get_extension_from_mime_type, which is case-insensitive;mimetypes.guess_typeis also case-insensitive on the extension.Impact
guess()feeds themimetypefield when uploading files (core/models/_files.py):Uppercase extensions are common in practice (phone cameras, scanners, Windows), so those uploads currently get
application/octet-streaminstead of the correct content type.Suggested fix
Normalize the suffix before the lookup:
and update
test_extension_lookup_is_case_sensitiveto assert the case-insensitive result. Happy to open the PR if you agreeguess()should be case-insensitive like its sibling.