Skip to main content

Stream one HTTP response as multiple parts. For Django, FastAPI, and Starlette.

Project description

multipart-response

Stream one HTTP response as multiple parts. For Django, FastAPI, and Starlette.

FastAPI

Install the FastAPI adapter:

uv add "multipart-response[fastapi]"

Yield parts from an endpoint:

from fastapi import FastAPI
from multipart_response.fastapi import HTMLMultipartResponse

app = FastAPI()

@app.get("/updates", response_class=HTMLMultipartResponse)
async def updates():
    yield "<p>Ready</p>"
    yield "<p>Done</p>"

Each part is sent when it is yielded:

Content-Type: multipart/mixed; boundary=multipart-...

--multipart-...
content-length: 12
content-type: text/html; charset=utf-8

<p>Ready</p>
--multipart-...
content-length: 11
content-type: text/html; charset=utf-8

<p>Done</p>
--multipart-...--

The same API is available from multipart_response.starlette.

Django

Install the Django adapter:

uv add "multipart-response[django]"

Return explicit parts from a view:

from multipart_response.django import MultipartResponse, Part


def updates(request):
    def parts():
        yield Part("<p>Ready</p>")
        yield Part("<p>Done</p>")

    return MultipartResponse(parts())

Part uses Django's content, content_type, charset, and headers conventions. HTML is the default content type, as it is for Django's HttpResponse.

Set headers on one part through its constructor or headers:

part = Part(
    "<p>Ready</p>",
    headers={"HX-Target": "#status"},
)
part.headers["HX-Swap"] = "innerHTML"

Serialize Python data with Django's JsonResponse rules:

from multipart_response.django import JsonPart

part = JsonPart({"status": "ready"})

Use an async part source when Django runs under ASGI:

async def updates(request):
    async def parts():
        yield Part("<p>Ready</p>")
        yield Part("<p>Done</p>")

    return MultipartResponse(parts())

MultipartResponse subclasses Django's StreamingHttpResponse, so Django handles it like any other streaming response.

Django 4.2 or later is required. Sync iterators suit WSGI. Async iterators suit ASGI.

htmx

With the hx-multipart extension, each part is one swap. Part headers pick the target:

@app.get("/dashboard", response_class=HTMLMultipartResponse)
async def dashboard():
    yield ("<p>Ready</p>", {"HX-Target": "#status"})
    yield ("<li>New</li>", {"HX-Target": "#reports", "HX-Swap": "beforeend"})

Other part types

Use explicit parts when one response mixes content types:

from multipart_response.fastapi import JSONPart, Multipart, MultipartResponse, Part, TextPart

@app.get("/report", response_class=MultipartResponse)
async def report():
    yield TextPart("Preparing")
    yield JSONPart({"status": "ready"})
    yield Part(chunk_stream(), media_type="video/mp4")
    yield Multipart([...], subtype="alternative")

Django's Part uses content_type instead of media_type.

Notes

  • Return MultipartResponse([...], status_code=..., headers=...) with FastAPI or Starlette.
  • Return MultipartResponse([...], status=..., reason=..., headers=...) with Django.
  • The dependency-free core exports Multipart, MultipartPart, and MultipartWriter.
  • Boundaries and headers are validated against RFC 2046 limits.
  • Body chunks are checked for boundary collisions.

License

BSD-3-Clause

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multipart_response-0.4.0.tar.gz (72.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

multipart_response-0.4.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file multipart_response-0.4.0.tar.gz.

File metadata

  • Download URL: multipart_response-0.4.0.tar.gz
  • Upload date:
  • Size: 72.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for multipart_response-0.4.0.tar.gz
Algorithm Hash digest
SHA256 d9cbdc88d702b3b6ff0099d4997104ab407b2c4adca92a5a8cf8779e7ab66360
MD5 c26c230a43d75ea286e3a4803a476bc5
BLAKE2b-256 62decaec4298219574dca9f1c12dedbf5056b18864ac60453a18064850816529

See more details on using hashes here.

Provenance

The following attestation bundles were made for multipart_response-0.4.0.tar.gz:

Publisher: release.yml on scriptogre/multipart-response

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file multipart_response-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for multipart_response-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c4163645c63737e95f51f6f96110fe03dfb5db72385d5a324abc2708d6cc022
MD5 58d3f6e7907b87ad6e831af1f6921a80
BLAKE2b-256 8d4720c42fc4c8ba8901918c73d127dd6e7b9957969d5776bb20e62cde835966

See more details on using hashes here.

Provenance

The following attestation bundles were made for multipart_response-0.4.0-py3-none-any.whl:

Publisher: release.yml on scriptogre/multipart-response

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page