microdot.sse — Server-Sent Events¶
Server-Sent Events (SSE) ist ein einfaches Einweg-Push-Protokoll: Der Client öffnet einen normalen HTTP-Request an Content-Type: text/event-stream, und der Server hält die Verbindung offen und schreibt formatierte Ereignisse, sobald sie auftreten. Der Browser stellt den Stream als JavaScript-EventSource-Objekt bereit. Im Vergleich zu WebSockets ist SSE einfacher, wenn nur der Server pusht; der Client fordert immer an.
Die typische Verwendung bei Kameras ist die Veröffentlichung von Erkennungen / Sensormesswerten / Statusaktualisierungen an ein Telefon oder Dashboard in der Geschwindigkeit, in der sie auftreten, ohne dass das Dashboard pollen muss.
class SSE¶
- class microdot.sse.SSE¶
Das Handle, das die Route erhält. Wird Handlern als zweites Argument übergeben, wenn
with_sse()verwendet wird.- async send(data, event: str | None = None, event_id: str | None = None, retry: int | None = None, comment: bool = False)¶
Pusht ein einzelnes Ereignis an den Client.
- data
Die Ereignis-Nutzlast. Strings und Bytes werden unverändert gesendet. Dicts und Listen werden zu JSON serialisiert. Alles andere wird mit
str()umgewandelt.- event
Optionaler Ereignisname – die
EventSourcedes Browsers leitet an einen JavaScript-Listener desselben Namens weiter, wenn dies gesetzt ist.- event_id
Optionale Ereignis-ID – der Browser sendet sie als
Last-Event-IDzurück, falls die Verbindung abbricht und wiederhergestellt wird, was es dem Server ermöglicht, dort fortzufahren, wo er aufgehört hat.- retry
Wiederverbindungsverzögerung in Sekunden; der Browser verwendet diese, falls die Verbindung abbricht.
- comment
Wenn
True, wird die Nutzlast als SSE-Kommentarzeile gesendet (vom Browser ignoriert). Nützlich als Keep-Alive-Heartbeat, um zu verhindern, dass NAT-Timeouts einen ansonsten untätigen Stream schließen.
Decorators auf Modulebene¶
- microdot.sse.with_sse(f)¶
Decorator, der eine Route in einen SSE-Endpunkt verwandelt. Der Handler erhält den Request und ein
SSE-Objekt:from microdot import Microdot from microdot.sse import with_sse app = Microdot() @app.get('/events') @with_sse async def events(request, sse): import asyncio while True: await sse.send({'temp': read_sensor()}, event='reading') await asyncio.sleep(1)
Die Lebensdauer des Handlers entspricht der Lebensdauer des Streams – er läuft so lange, wie der Client verbunden bleibt. Eine Abbruchanforderung (der Client trennt die Verbindung, der Server fährt herunter) propagiert als
asyncio.CancelledError, die das Framework verschluckt.
- microdot.sse.sse_response(request, event_function, *args, **kwargs)¶
Low-Level-Einstiegspunkt: gibt das Response-Tupel zurück, das
with_sse()unter der Haube zurückgibt. Nützlich, wenn ein SSE-Endpunkt benutzerdefinierte Header oder Statuscodes benötigt, die der Decorator nicht zulässt:from microdot.sse import sse_response @app.get('/events') async def events(request): if not request.g.current_user: return 401 async def emit(req, sse): await sse.send('hello') return sse_response(request, emit)
event_function nimmt
(request, sse, *args, **kwargs)entgegen und verwendetawait sse.send(...), um Ereignisse zu pushen.
Die SSE-Antwort setzt Content-Type: text/event-stream und hält die Verbindung offen, bis event_function zurückkehrt oder der Client die Verbindung trennt. Verwenden Sie eine while True-Schleife mit einem await asyncio.sleep zwischen den Sends, um eine Hot-Loop zu vermeiden.