Summary
Two limitations in context.fetch() force integrations to bypass the SDK entirely and use aiohttp directly, which defeats the purpose of having a unified HTTP abstraction.
Problem 1: Binary File Downloads
context.fetch() internally calls response.text() for all non-JSON responses (integration.py, ~line 511), which decodes bytes as UTF-8 text. This corrupts binary content such as images, PDFs, and zip files.
There is no way to retrieve raw bytes through the current API.
Example from the Box integration — the integration has to access the internal context._session directly to call response.read():
file_content = await response.read()
content_base64 = base64.b64encode(file_content).decode("utf-8")
Problem 2: Multipart Form Uploads
context.fetch() only handles application/json and application/x-www-form-urlencoded content types. There is no support for multipart/form-data, which is required by APIs like Box's file upload endpoint.
Example from the Box integration — the integration constructs aiohttp.FormData manually and posts via context._session:
data = aiohttp.FormData()
data.add_field("attributes", json.dumps({...}), content_type="application/json")
data.add_field("file", file_content, filename=file_name, content_type=content_type)
async with context._session.post(url, data=data, headers=headers) as response:
...
The integration even includes a comment acknowledging the workaround: "We'll need to use a different approach for uploads."
Impact
Any integration that needs binary downloads or multipart uploads must:
- Declare
aiohttp as a direct dependency
- Access the private
context._session attribute (not part of the public API)
- Bypass
context.fetch() entirely
Affected integrations: box
Proposed Fix
- Add a
binary=True (or raw=True) parameter to context.fetch() that returns bytes instead of calling response.text().
- Add a
form_data parameter to context.fetch() that accepts a dict or list of fields and constructs a multipart/form-data request automatically.
These additions would keep integrations within the SDK abstraction layer and avoid exposing internal aiohttp internals.
Summary
Two limitations in
context.fetch()force integrations to bypass the SDK entirely and useaiohttpdirectly, which defeats the purpose of having a unified HTTP abstraction.Problem 1: Binary File Downloads
context.fetch()internally callsresponse.text()for all non-JSON responses (integration.py, ~line 511), which decodes bytes as UTF-8 text. This corrupts binary content such as images, PDFs, and zip files.There is no way to retrieve raw bytes through the current API.
Example from the Box integration — the integration has to access the internal
context._sessiondirectly to callresponse.read():Problem 2: Multipart Form Uploads
context.fetch()only handlesapplication/jsonandapplication/x-www-form-urlencodedcontent types. There is no support formultipart/form-data, which is required by APIs like Box's file upload endpoint.Example from the Box integration — the integration constructs
aiohttp.FormDatamanually and posts viacontext._session:The integration even includes a comment acknowledging the workaround: "We'll need to use a different approach for uploads."
Impact
Any integration that needs binary downloads or multipart uploads must:
aiohttpas a direct dependencycontext._sessionattribute (not part of the public API)context.fetch()entirelyAffected integrations: box
Proposed Fix
binary=True(orraw=True) parameter tocontext.fetch()that returnsbytesinstead of callingresponse.text().form_dataparameter tocontext.fetch()that accepts a dict or list of fields and constructs amultipart/form-datarequest automatically.These additions would keep integrations within the SDK abstraction layer and avoid exposing internal
aiohttpinternals.