microdot.websocket --- WebSocket サポート

WebSocket は HTTP 上の双方向の永続的な接続です。アップグレードハンドシェイクの後、クライアントとサーバーは同じソケット上でフレーム化されたメッセージを送受信します。SSE(一方向プッシュ)や通常の HTTP ポーリングでは安価に実現できない全二重通信が、カメラとブラウザ側アプリケーションの間で必要な場合に使用します。

class WebSocket

class microdot.websocket.WebSocket(request)

ルートが受け取るハンドルです。with_websocket() を使用している場合、ハンドラに 2 番目の引数として渡されます。直接構築しないでください。

クラス属性

max_message_length: int

receive() が受け入れる最大ペイロードサイズです。これを超えるメッセージは WebSocketError を発生させ、接続を閉じます。0 を指定するとチェックが無効になります(これを設定する場合はメモリ枯渇攻撃に注意してください)。-1(デフォルト)は Request.max_body_length を使用します。

CONT: int

継続フレームのオペコード 0x0 です。同じメッセージの前のフレームのペイロードを継続するフレームを示します。Microdot 自身は継続フレームを生成せず(各メッセージは単一のフレームとして送信されます)、受信時には拒否しますが、カスタムフレーミングを実装するアプリケーションのために定数が公開されています。

TEXT: int

テキストフレームのオペコード 0x1 です。datastr の場合に send() が自動的に選択するオペコードで、ペイロードは送出時に UTF-8 でエンコードされます。

BINARY: int

バイナリフレームのオペコード 0x2 です。databytes / bytearray の場合に send() が自動的に選択するオペコードで、ペイロードはそのまま送信されます。

CLOSE: int

クローズフレームのオペコード 0x8 です。close() によって送信されます。これを受信すると receive() から WebSocketError("Websocket connection closed")が発生します。

PING: int

ピングフレームのオペコード 0x9 です。Microdot は受信したピングに対して receive() 内で自動的に対応する PONG で応答します。アプリケーションが通常これを観測することはありません。

PONG: int

ポングフレームのオペコード 0xA です。PING への応答として自動的に送信されます。受信したポングは黙って破棄されます。

インスタンス属性

request: microdot.Request

発信元の microdot.Request です。ルートハンドラが受け取ったものと同じオブジェクトです。

closed: bool

close() が実行されると True になります。クリーンアップ処理で二重クローズを避けるために確認します。

メソッド

async receive()

クライアントからの次のメッセージを待って返します。戻り値の型はフレームのオペコードに一致します。テキストフレームの場合は str、バイナリフレームの場合は bytes です。ping フレームには自動的に pong で応答します。pong フレームは黙って破棄されます。close フレームは WebSocketError("Websocket connection closed")を発生させます。

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

data をクライアントに送信します。文字列はテキストフレームとして、バイトはバイナリフレームとして送信されます。opcode を明示的に渡すとこれを上書きできます。

async close()

クローズフレームを送信し、接続を閉じた状態としてマークします。with_websocket() のラッパーが終了するときに自動的に呼び出されます。

class WebSocketError

exception microdot.websocket.WebSocketError

接続が終了したかプロトコルに違反した場合に WebSocket.receive() 内で発生します。通常のクライアント切断を検出するためにルート内で使用します:

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

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

microdot.websocket.with_websocket(f)

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

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)

ハンドラの寿命は接続の寿命と等しくなります。リターン、例外の送出、またはクライアントの切断によって WebSocket は正常に閉じられます。

async microdot.websocket.websocket_upgrade(request)

低レベルのアップグレードヘルパーです。アップグレードを条件付きで行うべき場合(例えば認可チェックが通過した後にのみ行う場合)にルート内で使用します:

@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())

アップグレードされた WebSocket を返します。ハンドラは処理が完了したら microdot.Response.already_handled を返す(または例外を送出する)必要があります。microdot はすでにソケットを引き継いでいます。

この実装は標準のテキストおよびバイナリのオペコード、ping / pong、および正常なクローズをサポートします。フラグメント化された(継続)フレームはサポートされません。各メッセージは単一のフレームとして送信されますが、これは小さなメッセージが典型的なカメラアプリケーションには適しています。