Skip to content

v0.3.0 Release Notes¶

Release Date: June 2025

This release adds real-time communication primitives and a modular routing system to Cello, enabling WebSocket connections, Server-Sent Events, multipart file uploads, and Flask-style Blueprints for organizing large applications.


Highlights¶

  • WebSocket Support -- Full-duplex communication over a single TCP connection
  • Server-Sent Events (SSE) -- Push updates from server to client over HTTP
  • Multipart Form Handling -- File uploads and mixed form data
  • Blueprints -- Modular route grouping with prefix and middleware isolation

New Features¶

WebSocket Support¶

Cello now supports WebSocket connections through tokio-tungstenite, with a clean Python decorator API.

from cello import App

app = App()

@app.websocket("/ws/chat")
async def chat(ws):
    while True:
        message = await ws.receive()
        await ws.send(f"Echo: {message}")

Capabilities:

  • Text and binary message frames
  • Ping/pong heartbeat (automatic)
  • Graceful connection close with status codes
  • Per-connection state via the ws object
  • Concurrent connections managed by Tokio

Server-Sent Events (SSE)¶

Push real-time updates to clients over a standard HTTP connection.

from cello import App, SseStream
import asyncio

app = App()

@app.get("/events")
async def events(request):
    async def stream():
        for i in range(100):
            yield {"event": "update", "data": f"tick {i}"}
            await asyncio.sleep(1)
    return SseStream(stream())

SSE responses automatically set Content-Type: text/event-stream and keep the connection open. The Rust layer handles buffering and flush semantics.

Multipart Form Handling¶

Upload files and process mixed form data using the multer crate under the hood.

@app.post("/upload")
async def upload(request):
    files = await request.files()
    form = await request.form()

    for f in files:
        content = await f.read()
        save_file(f.filename, content)

    return {"uploaded": len(files), "name": form.get("name")}

Features:

Feature Description
Multiple files Upload several files in one request
Size limits Configurable per-file and total limits
Streaming Large files are streamed, not buffered entirely in memory
MIME detection Automatic content-type detection

Blueprints¶

Organize routes into reusable modules with shared prefixes, middleware, and guards.

from cello import App, Blueprint

users_bp = Blueprint("/users")

@users_bp.get("/")
def list_users(request):
    return {"users": []}

@users_bp.get("/{id}")
def get_user(request):
    return {"id": request.params["id"]}

app = App()
app.register_blueprint(users_bp)
# Routes: GET /users/, GET /users/{id}

Blueprint features:

  • URL prefix applied to all routes in the group
  • Middleware scoped to the blueprint
  • Nested blueprints for hierarchical organization
  • Independent error handlers per blueprint
# Nested blueprints
api = Blueprint("/api")
v1 = Blueprint("/v1")
v1.register_blueprint(users_bp)
api.register_blueprint(v1)
app.register_blueprint(api)
# Routes: GET /api/v1/users/, GET /api/v1/users/{id}

Improvements¶

Performance¶

  • Optimized routing -- Radix tree now pre-compiles route patterns at registration time
  • Zero-copy WebSocket frames -- Messages pass through Rust without Python copies where possible
  • Faster multipart parsing -- Streaming parser avoids buffering entire request bodies

Developer Experience¶

  • Better error messages for malformed routes and missing handlers
  • Debug logging for WebSocket lifecycle events (connect, message, disconnect)
  • Improved --debug mode with request/response body inspection

Bug Fixes¶

  • Fixed route conflicts when registering overlapping path parameters
  • Fixed Content-Length header not being set for empty responses
  • Fixed incorrect HTTP status code for HEAD requests on missing routes
  • Fixed memory growth when many short-lived connections were opened rapidly

Dependencies Added¶

Dependency Version Purpose
tokio-tungstenite 0.21 WebSocket protocol support
multer 3.0 Multipart form parsing

Migration from v0.2.0¶

No breaking changes. All v0.2.0 applications work without modification.

New optional features¶

  1. WebSocket routes -- Use @app.websocket("/path") to add WebSocket endpoints.
  2. SSE responses -- Return SseStream(generator) from any GET handler.
  3. File uploads -- Call await request.files() in handlers that accept multipart data.
  4. Blueprints -- Refactor existing routes into Blueprint objects for better organization.
pip install --upgrade cello-framework

Full Changelog¶

See the complete changelog for all changes in this release.