microdot.websocket — WebSocket support

WebSockets are a two-way persistent connection over HTTP – after an upgrade handshake, client and server send and receive framed messages on the same socket. Use them when the camera and a browser-side application need full-duplex traffic that SSE (one-way push) and plain HTTP polling cannot give them cheaply.

class WebSocket

class microdot.websocket.WebSocket(request)

The handle the route receives. Passed to handlers as the second argument when with_websocket() is in use; do not construct directly.

Class attributes

max_message_length: int

Maximum payload size that receive() will accept. Messages larger than this raise WebSocketError and close the connection. 0 disables the check (be aware of memory- exhaustion attacks if you set this). -1 (default) uses Request.max_body_length.

CONT: int

Continuation-frame opcode, 0x0. Marks a frame that continues the payload of the previous frame for the same message. Microdot does not generate continuation frames itself (each message goes out as a single frame) and rejects them on receive, but the constant is exposed for applications that implement custom framing.

TEXT: int

Text-frame opcode, 0x1. The opcode send() picks automatically when data is a str; the payload is UTF-8-encoded on the way out.

BINARY: int

Binary-frame opcode, 0x2. The opcode send() picks automatically when data is bytes / bytearray; the payload is sent verbatim.

CLOSE: int

Close-frame opcode, 0x8. Sent by close(); receiving one raises WebSocketError (“Websocket connection closed”) out of receive().

PING: int

Ping-frame opcode, 0x9. Microdot answers incoming pings with a matching PONG automatically inside receive(); the application does not normally observe them.

PONG: int

Pong-frame opcode, 0xA. Sent automatically in reply to a PING. Incoming pongs are silently dropped.

Instance attributes

request: microdot.Request

The originating microdot.Request – the same object the route handler received.

closed: bool

True once close() has run. Inspect to avoid double- closing in cleanup paths.

Methods

async receive()

Wait for and return the next message from the client. The return type matches the frame opcode: str for text frames, bytes for binary frames. ping frames are answered automatically with a pong; pong frames are silently dropped; a close frame raises WebSocketError (“Websocket connection closed”).

async send(data, opcode: int | None = None)

Send data to the client. Strings are sent as text frames, bytes as binary frames; pass opcode explicitly to override.

async close()

Send a close frame and mark the connection as closed. Called automatically when with_websocket()’s wrapper exits.

class WebSocketError

exception microdot.websocket.WebSocketError

Raised inside WebSocket.receive() when the connection ends or the protocol is violated. Use this in a route to detect normal client disconnects:

try:
    message = await ws.receive()
except WebSocketError:
    # client closed the connection

Module-level decorators

microdot.websocket.with_websocket(f)

Decorator that turns a route into a WebSocket endpoint. The handler receives the request and a WebSocket object:

from microdot import Microdot
from microdot.websocket import with_websocket

app = Microdot()

@app.get('/echo')
@with_websocket
async def echo(request, ws):
    while True:
        msg = await ws.receive()
        await ws.send(msg)

The handler’s lifetime equals the connection lifetime. Returning, raising, or a client disconnect closes the WebSocket cleanly.

async microdot.websocket.websocket_upgrade(request)

Low-level upgrade helper. Use this inside a route when the upgrade should happen conditionally – e.g. only after an authorization check passes:

@app.get('/private')
async def private(request):
    if not authenticate(request):
        abort(401)
    ws = await websocket_upgrade(request)
    while True:
        msg = await ws.receive()
        await ws.send(msg.upper())

Returns the upgraded WebSocket. The handler must return microdot.Response.already_handled (or raise) once it’s done – microdot has already taken over the socket.

The implementation supports the standard text and binary opcodes, ping / pong, and a clean close. Fragmented (continuation) frames are not supported – each message is sent as a single frame, which is appropriate for the typical small-message camera applications.