tornado.websocket — ブラウザとの双方向通信

WebSocket プロトコルの実装。

WebSocket は、ブラウザとサーバー間の双方向通信を可能にします。WebSocket は、すべての主要ブラウザの現在のバージョンでサポートされています。

このモジュールは、RFC 6455 で定義されている WebSocket プロトコルの最終バージョンを実装しています。

バージョン 4.0 で変更: ドラフト 76 プロトコルバージョンのサポートを削除しました。

class tornado.websocket.WebSocketHandler(application: Application, request: HTTPServerRequest, **kwargs: Any)[ソース]

基本的な WebSocket ハンドラを作成するには、このクラスをサブクラス化します。

受信メッセージを処理するには on_message をオーバーライドし、クライアントにメッセージを送信するには write_message を使用します。openon_close をオーバーライドして、接続の開始と終了を処理することもできます。

カスタムアップグレードレスポンスヘッダーは、set_default_headers または prepare をオーバーライドすることで送信できます。

JavaScript インターフェースの詳細は、http://dev.w3.org/html5/websockets/ を参照してください。プロトコルは http://tools.ietf.org/html/rfc6455 で規定されています。

受信したすべてのメッセージをクライアントにエコーバックする WebSocket ハンドラの例を次に示します

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        print("WebSocket opened")

    def on_message(self, message):
        self.write_message(u"You said: " + message)

    def on_close(self):
        print("WebSocket closed")

WebSocket は標準の HTTP 接続ではありません。「ハンドシェイク」は HTTP ですが、ハンドシェイク後は、プロトコルはメッセージベースです。そのため、Tornado HTTP 機能のほとんどは、このタイプのハンドラでは使用できません。使用できる通信方法は、write_message()ping()close() のみです。同様に、リクエストハンドラクラスは、get()post() ではなく、open() メソッドを実装する必要があります。

上記のハンドラをアプリケーションの /websocket にマッピングすると、JavaScript で次のように呼び出すことができます

var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function() {
   ws.send("Hello, world");
};
ws.onmessage = function (evt) {
   alert(evt.data);
};

このスクリプトは、「You said: Hello, world」というアラートボックスを表示します。

Webブラウザは、JavaScript からの他のネットワークアクセスを制御する同一オリジンポリシーを使用する代わりに、任意のサイトが他のサイトへの WebSocket 接続を開くことを許可します。これは驚くべきことであり、潜在的なセキュリティホールであるため、Tornado 4.0 以降、WebSocketHandler は、クロスオリジン WebSocket を受信したいアプリケーションが check_origin メソッドをオーバーライドすることによってオプトインすることを要求します(詳細は、そのメソッドのドキュメントを参照してください)。そうしないと、WebSocket 接続時に 403 エラーが発生する可能性が高くなります。

自己署名証明書を使用してセキュア WebSocket 接続(wss://)を使用する場合、ブラウザからの接続は、「この証明書を受け入れる」ダイアログを表示したいが、表示する場所がないため失敗する可能性があります。 WebSocket 接続が成功する前に、同じ証明書を使用して通常の HTML ページにアクセスして、証明書を受け入れる必要があります。

アプリケーション設定 websocket_ping_interval にゼロ以外の値が設定されている場合、ping が定期的に送信され、websocket_ping_timeout 前に応答が受信されない場合、接続は閉じられます。

アプリケーション設定 websocket_max_message_size(デフォルト 10MiB)を超えるメッセージは受け入れられません。

バージョン 4.5 で変更: websocket_ping_intervalwebsocket_ping_timeoutwebsocket_max_message_size が追加されました。

イベントハンドラ

WebSocketHandler.open(*args: str, **kwargs: str) Optional[Awaitable[None]][ソース]

新しい WebSocket が開かれたときに呼び出されます。

open への引数は、tornado.web.RequestHandler.get への引数と同様に、tornado.web.URLSpec 正規表現から抽出されます。

open はコルーチンです。on_message は、open が戻るまで呼び出されません。

バージョン 5.1 で変更: open はコルーチンです。

WebSocketHandler.on_message(message: Union[str, bytes]) Optional[Awaitable[None]][source]

WebSocket で受信したメッセージを処理します。

このメソッドはオーバーライドする必要があります。

バージョン 4.5 で変更: on_message はコルーチンにすることができます。

WebSocketHandler.on_close() None[source]

WebSocket が閉じられたときに呼び出されます。

接続が正常に閉じられ、ステータスコードまたは理由のフレーズが提供された場合、これらの値は属性 self.close_code および self.close_reason として利用できます。

バージョン 4.0 で変更: close_code および close_reason 属性が追加されました。

WebSocketHandler.select_subprotocol(subprotocols: List[str]) Optional[str][source]

サブプロトコルネゴシエーションを実装するには、オーバーライドします。

subprotocols は、クライアントによって提案されたサブプロトコルを識別する文字列のリストです。 このメソッドをオーバーライドして、それらの文字列のいずれかを返して選択するか、None を返してサブプロトコルを選択しないようにすることができます。

サブプロトコルの選択に失敗しても、接続は自動的に中止されません。ただし、クライアントは、提案されたサブプロトコルのいずれも選択されなかった場合、接続を閉じる場合があります。

リストが空の場合、このメソッドは None を返す必要があります。 このメソッドは、サブプロトコルが提案されていない場合でも、常に正確に 1 回呼び出されるため、ハンドラはこの事実を通知できます。

バージョン 5.1 で変更: 以前は、クライアントによってサブプロトコルが提案されていない場合、このメソッドは空のリストではなく、空の文字列を含むリストで呼び出されていました。

WebSocketHandler.selected_subprotocol

select_subprotocol によって返されるサブプロトコル。

バージョン 5.1 で追加。

WebSocketHandler.on_ping(data: bytes) None[source]

ping フレームを受信したときに呼び出されます。

出力

WebSocketHandler.write_message(message: Union[bytes, str, Dict[str, Any]], binary: bool = False) Future[None][source]

指定されたメッセージをこの WebSocket のクライアントに送信します。

メッセージは、文字列または辞書(json としてエンコードされます)です。 binary 引数が false の場合、メッセージは utf8 として送信されます。 バイナリモードでは、任意のバイト文字列が許可されます。

接続がすでに閉じている場合は、WebSocketClosedError を発生させます。 フロー制御に使用できる Future を返します。

バージョン 3.2 で変更: WebSocketClosedError が追加されました(以前は、閉じた接続は AttributeError を発生させていました)

バージョン 4.3 で変更: フロー制御に使用できる Future を返します。

バージョン 5.0 で変更: WebSocketClosedError を一貫して発生させます。 以前は、StreamClosedError を発生させる場合がありました。

WebSocketHandler.close(code: Optional[int] = None, reason: Optional[str] = None) None[source]

この WebSocket を閉じます。

クローズハンドシェイクが成功すると、ソケットは閉じられます。

code は、RFC 6455 セクション 7.4.1 で定義されている値から取得した、数値ステータスコードです。 reason は、接続が閉じられる理由に関するテキストメッセージです。これらの値はクライアントが利用できますが、WebSocket プロトコルでは解釈されません。

バージョン 4.0 で変更: codereason 引数が追加されました。

設定

WebSocketHandler.check_origin(origin: str) bool[source]

代替オリジンを許可するためのサポートを有効にするには、オーバーライドします。

origin 引数は、Origin HTTP ヘッダーの値、つまりこのリクエストを開始した URL です。このヘッダーを送信しないクライアントに対しては、このメソッドは呼び出されません。そのようなリクエストは常に許可されます(WebSocket を実装するすべてのブラウザがこのヘッダーをサポートしており、ブラウザ以外のクライアントには同じクロスサイトセキュリティ上の懸念がないためです)。

リクエストを受け入れる場合は True を、拒否する場合は False を返します。デフォルトでは、このホスト以外のホストでオリジンを持つすべてのリクエストを拒否します。

これは、WebSocket は通常の同一オリジンポリシーをバイパスすることができ、CORS ヘッダーを使用しないため、ブラウザに対するクロスサイトスクリプティング攻撃に対するセキュリティ保護です。

警告

これは重要なセキュリティ対策です。セキュリティへの影響を理解せずに無効にしないでください。特に、認証が Cookie ベースの場合、check_origin() で許可されるオリジンを制限するか、WebSocket 接続に独自の XSRF のような保護を実装する必要があります。詳細については、これらの 記事 を参照してください。

すべてのクロスオリジントラフィックを受け入れるには(Tornado 4.0 より前のデフォルト)、このメソッドをオーバーライドして常に True を返すようにします。

def check_origin(self, origin):
    return True

サイトの任意のサブドメインからの接続を許可するには、次のようにします。

def check_origin(self, origin):
    parsed_origin = urllib.parse.urlparse(origin)
    return parsed_origin.netloc.endswith(".mydomain.com")

バージョン 4.0 での新機能。

WebSocketHandler.get_compression_options() Optional[Dict[str, Any]][source]

接続の圧縮オプションを返すには、オーバーライドします。

このメソッドが None(デフォルト)を返すと、圧縮は無効になります。辞書(空の辞書でも)を返すと、圧縮は有効になります。辞書の内容を使用して、次の圧縮オプションを制御できます。

compression_level は圧縮レベルを指定します。

mem_level は、内部圧縮状態に使用されるメモリ量を指定します。

これらのパラメータの詳細は、こちらに記載されています:https://docs.python.org/3.6/library/zlib.html#zlib.compressobj

バージョン 4.1 での新機能。

バージョン 4.5 で変更: compression_levelmem_level が追加されました。

WebSocketHandler.set_nodelay(value: bool) None[source]

このストリームの no-delay フラグを設定します。

デフォルトでは、送信されるパケット数を最小限に抑えるために、小さなメッセージが遅延したり、結合されたりする可能性があります。これにより、Nagle のアルゴリズムと TCP 遅延 ACK の相互作用により、200〜500ミリ秒の遅延が発生することがあります。帯域幅の使用量が増加する可能性がありますが、この遅延を 줄이려면、WebSocket 接続が確立されたら、self.set_nodelay(True) を呼び出します。

詳細は、BaseIOStream.set_nodelay を参照してください。

バージョン 3.1 での新機能。

その他

WebSocketHandler.ping(data: Union[str, bytes] = b'') None[source]

リモートエンドに ping フレームを送信します。

data 引数を使用すると、少量のデータ(最大 125 バイト)を ping メッセージの一部として送信できます。すべての WebSocket 実装がこのデータをアプリケーションに公開するわけではないことに注意してください。

ping を手動で送信する代わりに、websocket_ping_interval アプリケーション設定の使用を検討してください。

バージョン 5.1 で変更: data 引数がオプションになりました。

WebSocketHandler.on_pong(data: bytes) None[source]

ping フレームへの応答を受信したときに呼び出されます。

exception tornado.websocket.WebSocketClosedError[source]

閉じられた接続に対する操作によって発生します。

バージョン 3.2 での新機能。

クライアントサイドのサポート

tornado.websocket.websocket_connect(url: Union[str, HTTPRequest], callback: Optional[Callable[[Future[WebSocketClientConnection]], None]] = None, ...) Awaitable[WebSocketClientConnection]

クライアント側の WebSocket サポート。

URL を受け取り、結果が WebSocketClientConnection である Future を返します。

compression_options は、WebSocketHandler.get_compression_options の戻り値と同じように解釈されます。

この接続は、2 つの動作スタイルをサポートしています。コルーチンスタイルでは、アプリケーションは通常、ループ内で read_message を呼び出します。

conn = yield websocket_connect(url)
while True:
    msg = yield conn.read_message()
    if msg is None: break
    # Do something with msg

コールバックスタイルでは、on_message_callbackwebsocket_connect に渡します。どちらのスタイルでも、None のメッセージは、接続が閉じられたことを示します。

subprotocols は、提案されたサブプロトコルを指定する文字列のリストです。選択されたプロトコルは、接続が完了したときに、接続オブジェクトの selected_subprotocol 属性で見つけることができます。

バージョン 3.2 で変更: URL の代わりに HTTPRequest オブジェクトも受け入れるようになりました。

バージョン 4.1 で変更: compression_optionson_message_callback が追加されました。

バージョン 4.5 で変更: WebSocketHandler と同じ意味を持つ ping_intervalping_timeoutmax_message_size 引数が追加されました。

バージョン 5.0 で変更: io_loop 引数 (バージョン 4.1 から非推奨) が削除されました。

バージョン 5.1 で変更: subprotocols 引数が追加されました。

バージョン 6.3 で変更: resolver 引数が追加されました。

class tornado.websocket.WebSocketClientConnection(request: HTTPRequest, on_message_callback: Optional[Callable[[Union[None, str, bytes]], None]] = None, ... )

WebSocket クライアント接続。

このクラスは直接インスタンス化すべきではありません。代わりに websocket_connect 関数を使用してください。

close(code: Optional[int] = None, reason: Optional[str] = None) None

WebSocket 接続を閉じます。

codereason については、WebSocketHandler.close のドキュメントを参照してください。

バージョン 3.2 での新機能。

バージョン 4.0 で変更: codereason 引数が追加されました。

write_message(...) Future[None]

WebSocket サーバーにメッセージを送信します。

ストリームが閉じている場合、WebSocketClosedError を発生させます。フロー制御に使用できる Future を返します。

バージョン 5.0 で変更: クローズされたストリームで発生する例外が StreamClosedError から WebSocketClosedError に変更されました。

read_message(callback: Optional[Callable[[Future[Union[None, str, bytes]]], None]] = None) Awaitable[Union[None, str, bytes]][ソース]

WebSocket サーバーからメッセージを読み取ります。

WebSocket の初期化時に on_message_callback が指定されている場合、この関数はメッセージを返しません。

結果がメッセージである Future を返します。接続が閉じている場合は None を返します。callback 引数が指定されている場合、Future が準備完了になったときに、その Future を使用してコールバックが呼び出されます。

ping(data: bytes = b'') None[ソース]

リモートエンドに ping フレームを送信します。

data 引数を使用すると、少量のデータ(最大 125 バイト)を ping メッセージの一部として送信できます。すべての WebSocket 実装がこのデータをアプリケーションに公開するわけではないことに注意してください。

ping を手動で送信する代わりに、websocket_connect への ping_interval 引数の使用を検討してください。

バージョン 5.1 で追加。

property selected_subprotocol: Optional[str]

サーバーによって選択されたサブプロトコル。

バージョン 5.1 で追加。