Skip to content

context.fetch() does not support binary responses or multipart form uploads #32

@Shubhank-Jonnada

Description

@Shubhank-Jonnada

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

  1. Add a binary=True (or raw=True) parameter to context.fetch() that returns bytes instead of calling response.text().
  2. 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.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions