Skip to content

Conversation

Copy link

Copilot AI commented Jan 31, 2026

FromFiles and FromText parameters were not generating any request body documentation in OpenAPI/Swagger, making file upload endpoints invisible in the documentation UI.

Changes

blacksheep/server/openapi/v3.py

  • Added _get_files_binder() to detect FilesBinder in handlers
  • Updated get_request_body() to generate multipart/form-data schema when FilesBinder is present without a BodyBinder
  • Schema generates type: array with format: binary items for file uploads

tests/test_openapi_v3.py

  • Added test_handles_from_files_multipart_docs()
  • Added test_handles_from_text_docs()

Example

Previously, this endpoint generated no request body documentation:

@app.router.post("/upload")
async def upload_file(files: FromFiles):
    return 'ok'

Now generates:

requestBody:
    content:
        multipart/form-data:
            schema:
                type: array
                items:
                    type: string
                    format: binary
    required: true

The file upload form now renders correctly in Swagger UI.

Original prompt

work on #546

Created from Copilot CLI via the copilot delegate command.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits January 31, 2026 07:19
Co-authored-by: RobertoPrevato <2576032+RobertoPrevato@users.noreply.github.com>
Co-authored-by: RobertoPrevato <2576032+RobertoPrevato@users.noreply.github.com>
Co-authored-by: RobertoPrevato <2576032+RobertoPrevato@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix issue 546 with user feedback processing Generate OpenAPI documentation for FromFiles and FromText parameters Jan 31, 2026
Copilot AI requested a review from RobertoPrevato January 31, 2026 07:25
@RobertoPrevato
Copy link
Member

This is a great start! However, I would like something more.

I would like to support defining custom BodyBinder classes that describe complex structures, and have them generated accordingly. Example of what I was planning to do:

# In the framework:
class FromMultipart:
    ...


class MultipartBinder(BodyBinder):
    """This class allows to define complex objects to be received as multipart form data"""

    handle = FromMultipartFormData

    @property
    def content_type(self) -> str:
        return "multipart/form-data"
        
    ...  # binding logic


# User defined example:

class Address:
    street: str
    city: str

class ExampleClass:
    id: UUID
    addresses: list[Address]
    profile_image: bytes

@app.router.post("/upload")
async def create_item(data: FromMultipart[ExampleClass]):
    # data.value.id is UUID
    # data.value.addresses is a list of Address
    # data.value.profile_image is a bytes array containing the image
    return 'ok'

Would generate the following OpenAPI Specification:

requestBody:
  content:
    multipart/form-data: # Media type
      schema: # Request payload
        type: object
        properties: # Request parts
          id: # Part 1 (string value)
            type: string
            format: uuid
          address: # Part2 (object)
            type: object
            properties:
              street:
                type: string
              city:
                type: string
          profileImage: # Part 3 (an image)
            type: string
            format: binary

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.

2 participants