Skip to content

fix: generate body_content_type param when multiple content types share the same schema#1426

Open
shjellvik wants to merge 1 commit intoopenapi-generators:mainfrom
shjellvik:fix/duplicate-content-type-body-dispatch
Open

fix: generate body_content_type param when multiple content types share the same schema#1426
shjellvik wants to merge 1 commit intoopenapi-generators:mainfrom
shjellvik:fix/duplicate-content-type-body-dispatch

Conversation

@shjellvik
Copy link
Copy Markdown

Fixes issue #1276

Problem

When a requestBody lists multiple content types that all reference the same $ref schema, they all resolve to the same Python type. The generated _get_kwargs used a chain of if isinstance checks — but since
every branch matched, the last branch always won (typically multipart/form-data). It was impossible to make a JSON or form-urlencoded request.

# Generated (broken) — all three isinstance checks pass, multipart always wins
if isinstance(body, DnsCreate):
    _kwargs["json"] = body.to_dict()
    headers["Content-Type"] = "application/json"
if isinstance(body, DnsCreate):          # also matches!
    _kwargs["data"] = body.to_dict()
    headers["Content-Type"] = "application/x-www-form-urlencoded"
if isinstance(body, DnsCreate):          # also matches!
    _kwargs["files"] = body.to_multipart()
    headers["Content-Type"] = "multipart/form-data"

Fix

When duplicate Python types are detected across bodies, a body_content_type: str parameter is emitted (defaulting to the first content type in the spec), and dispatch uses if/elif string comparisons instead of
isinstance checks.

 # Generated (fixed)
 def _get_kwargs(
     *,
     body: DnsCreate | Unset = UNSET,
     body_content_type: str = "application/json",
 ) -> dict[str, Any]:
     ...
     if body_content_type == "application/json":
         _kwargs["json"] = body.to_dict()
         headers["Content-Type"] = "application/json"
     elif body_content_type == "application/x-www-form-urlencoded":
         _kwargs["data"] = body.to_dict()
         headers["Content-Type"] = "application/x-www-form-urlencoded"
     elif body_content_type == "multipart/form-data":
         _kwargs["files"] = body.to_multipart()
         headers["Content-Type"] = "multipart/form-data"

Endpoints with distinct body types (the existing behaviour) are unaffected.

Changes

  • parser/openapi.py — adds bodies_with_content_type_dispatch (detects duplicate types) and unique_body_types (deduplicates for type annotations) properties to Endpoint
  • templates/endpoint_macros.py.jinja — adds body_content_type to arguments and kwargs macros when needed
  • templates/endpoint_module.py.jinja — uses if/elif string dispatch when bodies_with_content_type_dispatch is true
  • end_to_end_tests/functional_tests/generated_code_execution/test_endpoint_bodies.py — functional tests verifying correct dispatch for JSON, form-urlencoded, and multipart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant