Implementation of the WebSocket protocol.
WebSockets allow for bidirectional communication between the browser and server.
WebSockets are supported in the current versions of all major browsers, although older versions that do not support WebSockets are still in use (refer to http://caniuse.com/websockets for details).
This module implements the final version of the WebSocket protocol as defined in RFC 6455. Certain browser versions (notably Safari 5.x) implemented an earlier draft of the protocol (known as “draft 76”) and are not compatible with this module.
Changed in version 4.0: Removed support for the draft 76 protocol version.
class tornado.websocket.WebSocketHandler(application, request, **kwargs)[source]
Subclass this class to create a basic WebSocket handler.
Override on_message
to handle incoming messages, and use
write_message
to send messages to the client. You can also
override open
and on_close
to handle opened and closed
connections.
Custom upgrade response headers can be sent by overriding
set_default_headers
or
prepare
.
See http://dev.w3.org/html5/websockets/ for details on the JavaScript interface. The protocol is specified at http://tools.ietf.org/html/rfc6455.
Here is an example WebSocket handler that echos back all received messages back to the client:
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")
WebSockets are not standard HTTP connections. The “handshake” is
HTTP, but after the handshake, the protocol is
message-based. Consequently, most of the Tornado HTTP facilities
are not available in handlers of this type. The only communication
methods available to you are write_message()
, ping()
, and
close()
. Likewise, your request handler class should implement
open()
method rather than get()
or post()
.
If you map the handler above to /websocket
in your application, you can
invoke it in JavaScript with:
var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function() {
ws.send("Hello, world");
};
ws.onmessage = function (evt) {
alert(evt.data);
};
This script pops up an alert box that says “You said: Hello, world”.
Web browsers allow any site to open a websocket connection to any other,
instead of using the same-origin policy that governs other network
access from javascript. This can be surprising and is a potential
security hole, so since Tornado 4.0 WebSocketHandler
requires
applications that wish to receive cross-origin websockets to opt in
by overriding the check_origin
method (see that
method’s docs for details). Failure to do so is the most likely
cause of 403 errors when making a websocket connection.
When using a secure websocket connection (wss://
) with a self-signed
certificate, the connection from a browser may fail because it wants
to show the “accept this certificate” dialog but has nowhere to show it.
You must first visit a regular HTML page using the same certificate
to accept it before the websocket connection will succeed.
If the application setting websocket_ping_interval
has a non-zero
value, a ping will be sent periodically, and the connection will be
closed if a response is not received before the websocket_ping_timeout
.
Messages larger than the websocket_max_message_size
application setting
(default 10MiB) will not be accepted.
Changed in version 4.5: Added websocket_ping_interval
, websocket_ping_timeout
, and
websocket_max_message_size
.
Event handlers
WebSocketHandler.open(*args, **kwargs)[source]
Invoked when a new WebSocket is opened.
The arguments to open
are extracted from the tornado.web.URLSpec
regular expression, just like the arguments to
tornado.web.RequestHandler.get
.
WebSocketHandler.on_message(message)[source]
Handle incoming messages on the WebSocket
This method must be overridden.
Changed in version 4.5: on_message
can be a coroutine.
WebSocketHandler.on_close()[source]
Invoked when the WebSocket is closed.
If the connection was closed cleanly and a status code or reason
phrase was supplied, these values will be available as the attributes
self.close_code
and self.close_reason
.
Changed in version 4.0: Added close_code
and close_reason
attributes.
WebSocketHandler.select_subprotocol(subprotocols)[source]
Invoked when a new WebSocket requests specific subprotocols.
subprotocols
is a list of strings identifying the
subprotocols proposed by the client. This method may be
overridden to return one of those strings to select it, or
None
to not select a subprotocol. Failure to select a
subprotocol does not automatically abort the connection,
although clients may close the connection if none of their
proposed subprotocols was selected.
WebSocketHandler.on_ping(data)[source]
Invoked when the a ping frame is received.
Output
WebSocketHandler.write_message(message, binary=False)[source]
Sends the given message to the client of this Web Socket.
The message may be either a string or a dict (which will be
encoded as json). If the binary
argument is false, the
message will be sent as utf8; in binary mode any byte string
is allowed.
If the connection is already closed, raises WebSocketClosedError
.
Returns a Future
which can be used for flow control.
Changed in version 3.2: WebSocketClosedError
was added (previously a closed connection
would raise an AttributeError
)
Changed in version 4.3: Returns a Future
which can be used for flow control.
Changed in version 5.0: Consistently raises WebSocketClosedError
. Previously could
sometimes raise StreamClosedError
.
WebSocketHandler.close(code=None, reason=None)[source]
Closes this Web Socket.
Once the close handshake is successful the socket will be closed.
code
may be a numeric status code, taken from the values
defined in RFC 6455 section 7.4.1.
reason
may be a textual message about why the connection is
closing. These values are made available to the client, but are
not otherwise interpreted by the websocket protocol.
Changed in version 4.0: Added the code
and reason
arguments.
Configuration
WebSocketHandler.check_origin(origin)[source]
Override to enable support for allowing alternate origins.
The origin
argument is the value of the Origin
HTTP
header, the url responsible for initiating this request. This
method is not called for clients that do not send this header;
such requests are always allowed (because all browsers that
implement WebSockets support this header, and non-browser
clients do not have the same cross-site security concerns).
Should return True to accept the request or False to reject it. By default, rejects all requests with an origin on a host other than this one.
This is a security protection against cross site scripting attacks on browsers, since WebSockets are allowed to bypass the usual same-origin policies and don’t use CORS headers.
Warning
This is an important security measure; don’t disable it
without understanding the security implications. In
particular, if your authentication is cookie-based, you
must either restrict the origins allowed by
check_origin()
or implement your own XSRF-like
protection for websocket connections. See these
articles
for more.
To accept all cross-origin traffic (which was the default prior to Tornado 4.0), simply override this method to always return true:
def check_origin(self, origin):
return True
To allow connections from any subdomain of your site, you might do something like:
def check_origin(self, origin):
parsed_origin = urllib.parse.urlparse(origin)
return parsed_origin.netloc.endswith(".mydomain.com")
New in version 4.0.
WebSocketHandler.get_compression_options()[source]
Override to return compression options for the connection.
If this method returns None (the default), compression will be disabled. If it returns a dict (even an empty one), it will be enabled. The contents of the dict may be used to control the following compression options:
compression_level
specifies the compression level.
mem_level
specifies the amount of memory used for the internal compression state.
These parameters are documented in details here: https://docs.python.org/3.6/library/zlib.html#zlib.compressobj
New in version 4.1.
Changed in version 4.5: Added compression_level
and mem_level
.
WebSocketHandler.set_nodelay(value)[source]
Set the no-delay flag for this stream.
By default, small messages may be delayed and/or combined to minimize
the number of packets sent. This can sometimes cause 200-500ms delays
due to the interaction between Nagle’s algorithm and TCP delayed
ACKs. To reduce this delay (at the expense of possibly increasing
bandwidth usage), call self.set_nodelay(True)
once the websocket
connection is established.
See BaseIOStream.set_nodelay
for additional details.
New in version 3.1.
Other
WebSocketHandler.ping(data)[source]
Send ping frame to the remote end.
WebSocketHandler.on_pong(data)[source]
Invoked when the response to a ping frame is received.
exception tornado.websocket.WebSocketClosedError[source]
Raised by operations on a closed connection.
New in version 3.2.
Client-side support
tornado.websocket.websocket_connect(url, callback=None, connect_timeout=None, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, max_message_size=None)[source]
Client-side websocket support.
Takes a url and returns a Future whose result is a
WebSocketClientConnection
.
compression_options
is interpreted in the same way as the
return value of WebSocketHandler.get_compression_options
.
The connection supports two styles of operation. In the coroutine
style, the application typically calls
read_message
in a loop:
conn = yield websocket_connect(url)
while True:
msg = yield conn.read_message()
if msg is None: break
# Do something with msg
In the callback style, pass an on_message_callback
to
websocket_connect
. In both styles, a message of None
indicates that the connection has been closed.
Changed in version 3.2: Also accepts HTTPRequest
objects in place of urls.
Changed in version 4.1: Added compression_options
and on_message_callback
.
Changed in version 4.5: Added the ping_interval
, ping_timeout
, and max_message_size
arguments, which have the same meaning as in WebSocketHandler
.
Changed in version 5.0: The io_loop
argument (deprecated since version 4.1) has been removed.
class tornado.websocket.WebSocketClientConnection(request, on_message_callback=None, compression_options=None, ping_interval=None, ping_timeout=None, max_message_size=None)[source]
WebSocket client connection.
This class should not be instantiated directly; use the
websocket_connect
function instead.
close(code=None, reason=None)[source]
Closes the websocket connection.
code
and reason
are documented under
WebSocketHandler.close
.
New in version 3.2.
Changed in version 4.0: Added the code
and reason
arguments.
write_message(message, binary=False)[source]
Sends a message to the WebSocket server.
If the stream is closed, raises WebSocketClosedError
.
Returns a Future
which can be used for flow control.
Changed in version 5.0: Exception raised on a closed stream changed from StreamClosedError
to WebSocketClosedError
.
read_message(callback=None)[source]
Reads a message from the WebSocket server.
If on_message_callback was specified at WebSocket initialization, this function will never return messages
Returns a future whose result is the message, or None if the connection is closed. If a callback argument is given it will be called with the future when it is ready.