microdot.sse --- Server-Sent Events

Server-Sent Events(SSE)は、シンプルな一方向のプッシュプロトコルです。クライアントが Content-Type: text/event-stream に対して通常のHTTPリクエストを開き、サーバーは接続を開いたままにして、イベントが発生するたびにフォーマットされたイベントを書き込みます。ブラウザはこのストリームをJavaScriptの EventSource オブジェクトとして公開します。WebSocketと比較して、サーバーだけがプッシュする場合はSSEの方がシンプルです。クライアントは常にリクエストします。

カメラの典型的な用途は、検出結果 / センサーの読み取り値 / ステータス更新を、ダッシュボードがポーリングする必要なく、発生する速度で電話やダッシュボードにパブリッシュすることです。

class SSE

class microdot.sse.SSE

ルートが受け取るハンドルです。with_sse() が使用されている場合、第2引数としてハンドラに渡されます。

async send(data, event: str | None = None, event_id: str | None = None, retry: int | None = None, comment: bool = False)

単一のイベントをクライアントにプッシュします。

data

イベントのペイロードです。文字列とバイトはそのまま送信されます。辞書とリストはJSONにシリアライズされます。それ以外のものは str() で変換されます。

event

オプションのイベント名です -- これが設定されると、ブラウザの EventSource は同じ名前のJavaScriptリスナーにディスパッチします。

event_id

オプションのイベントIDです -- 接続が切断されて再接続された場合、ブラウザはこれを Last-Event-ID として返送し、サーバーが中断したところから再開できるようにします。

retry

秒単位の再接続遅延です。接続が切断された場合にブラウザがこれを使用します。

comment

True の場合、ペイロードはSSEのコメント行として送信されます(ブラウザからは無視されます)。NATのタイムアウトがアイドル状態のストリームを閉じるのを防ぐためのキープアライブのハートビートとして便利です。

モジュールレベルのデコレータ

microdot.sse.with_sse(f)

ルートをSSEエンドポイントに変えるデコレータです。ハンドラはリクエストと SSE オブジェクトを受け取ります:

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)

ハンドラの寿命はストリームの寿命と等しくなります -- クライアントが接続されている限り実行されます。キャンセル(クライアントの切断、サーバーのシャットダウン)は asyncio.CancelledError として伝播し、フレームワークがこれを飲み込みます。

microdot.sse.sse_response(request, event_function, *args, **kwargs)

低レベルのエントリポイント: with_sse() が内部で返すレスポンスタプルを返します。SSEエンドポイントが、デコレータでは許可されないカスタムヘッダーやステータスコードを必要とする場合に便利です:

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(request, sse, *args, **kwargs) を受け取り、await sse.send(...) を使用してイベントをプッシュします。

SSEレスポンスは Content-Type: text/event-stream を設定し、event_function が戻るかクライアントが切断するまで接続を開いたままにします。ホットループを避けるため、送信の間に await asyncio.sleep を挟んだ while True ループを使用してください。