OpenAPITools / OpenAPITools/openapi-generator

[BUG] [PYTHON-FASTAPI] required request body generates an optional body

Open
#21,236 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When defining a requestBody as required via the requestBody.required: true property in openapi (https://swagger.io/docs/specification/v3_0/describing-request-body/describing-request-body/#requestbody-content-and-media-types), I expect the generated server to generate a required body. However, the generated server sets the default value of that parameter to None, so FastAPI marks that body as optional.

Pydantic reference: https://fastapi.tiangolo.com/tutorial/body/#create-your-data-model
Image

openapi-generator version

7.12.0

I don't think this is a regression, as looking through the git history, didn't seem to have ever worked

OpenAPI declaration file content or url
openapi: 3.0.1
info:
  title: Sample API
  version: 1.0.0
paths:
  /pets:
    post:
      summary: Add a new pet
      requestBody:
        description: Optional description in *Markdown*
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Pet"
      responses:
        "201":
          description: Created

components:
  schemas:
    Pet:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        tag:
          type: string

Generation Details
openapi-generator generate -i openapi.yml -g python-fastapi -o server

This generates something like this

@router.post(
    "/pets",
    responses={
        201: {"description": "Created"},
    },
    tags=["default"],
    summary="Add a new pet",
    response_model_by_alias=True,
)
async def pets_post(
    pet: Annotated[Pet, Field(description="Optional description in *Markdown*")] = Body(None, description="Optional description in *Markdown*"),
) -> None:

note the pet field value: Body(None, description="Optional description in *Markdown*"), the Body has None as a default argument, so FastAPI marks that as optional.
The expected field value should be something like just Body(description="Optional description in *Markdown*") so pydantic marks that as required

Note: the Path param uses something like Path(..., description="description"), pydantic used to require ... as an argument to mark the field as a required, but this is not required in pydantic's newer versions, just omit that first default argument. See: https://stackoverflow.com/a/74884189

Related issues/PRs

Something similar has been done previously with the Path param https://github.com/OpenAPITools/openapi-generator/pull/17532, but this fix is not exactly the same (the parameter should not always be required as the path param, but rely on requestBody.required property to set the default value to None or not)

Suggest a fix

The problem is in this file:
https://github.com/OpenAPITools/openapi-generator/blob/f2813716fb815dae0e5bc6b2219452b3303f4934/modules/openapi-generator/src/main/resources/python-fastapi/endpoint_argument_definition.mustache

And in the definition of the Body parameter

Image

When settings the first argument as None, we must check if the requestBody.required property is set to true, and in that case, omit the first argument entirely.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with modules/openapi-generator/src/main/resources/python-fastapi/endpoint_argument_definition.mustache and reproduce the issue using the provided OpenAPI declaration and generation command. Check the generated pets_post endpoint's Body argument against requestBody.required. Done means required bodies omit the None default while optional bodies retain their optional behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.