Documentation for pulsar 0.9.2. For development docs, go here.
'''The :mod:`pulsar.apps.ws` contains WSGI_ middleware for
handling the WebSocket_ protocol.
Web sockets allow for bidirectional communication between the browser
and server. Pulsar implementation uses the WSGI middleware
:class:`.WebSocket` for the handshake_ and a class derived from
:class:`.WS` handler for the communication part.
This is a Web Socket handler which echos all received messages
back to the client::
from pulsar.apps import wsgi, ws
class EchoWS(ws.WS):
def on_message(self, websocket, message):
websocket.write(message)
To create a valid :class:`.WebSocket` middleware initialise as follow::
wm = ws.WebSocket('/bla', EchoWS())
app = wsgi.WsgiHandler(middleware=(..., wm))
wsgi.WSGIServer(callable=app).start()
.. _WSGI: http://www.python.org/dev/peps/pep-3333/
.. _WebSocket: http://tools.ietf.org/html/rfc6455
.. _handshake: http://tools.ietf.org/html/rfc6455#section-1.3
API
==============
.. _websocket-middleware:
.. _websocket-handler:
WebSocket handler
~~~~~~~~~~~~~~~~~~~~
.. autoclass:: WS
:members:
:member-order: bysource
.. module:: pulsar.apps.ws.websocket
WebSocket
~~~~~~~~~~~~~~~~
.. autoclass:: WebSocket
:members:
:member-order: bysource
WebSocket protocol
~~~~~~~~~~~~~~~~~~~~
.. autoclass:: WebSocketProtocol
:members:
:member-order: bysource
'''
from pulsar.apps import data
from .websocket import WebSocket, WebSocketProtocol
[docs]class WS(object):
'''A web socket handler for both servers and clients.
It implements the asynchronous message passing for a
:class:`.WebSocketProtocol`.
On the server, the communication is started by the
:class:`.WebSocket` middleware after a successful handshake.
Override :meth:`on_message` to handle incoming string messages and
:meth:`on_bytes` to handle incoming ``bytes`` messages.
You can also override :meth:`on_open` and :meth:`on_close` to perform
specific tasks when the websocket is opened or closed.
These methods accept as first parameter the
:class:`.WebSocketProtocol` created during the handshake.
'''
[docs] def on_open(self, websocket):
'''Invoked when a new ``websocket`` is opened.
A web socket is opened straight after the upgrade headers are
sent (servers) or received (clients).
'''
pass
[docs] def on_message(self, websocket, message):
'''Handles incoming messages on the WebSocket.
This method should be overwritten
'''
pass
[docs] def on_ping(self, websocket, message):
'''Handle incoming ping ``message``.
By default it writes back the message as a ``pong`` frame.
'''
websocket.pong(message)
class PubSubClient(data.PubSubClient):
__slots__ = ('connection', 'channel')
def __init__(self, connection, channel):
self.connection = connection
self.channel = channel
def __call__(self, channel, message):
self.connection.write(message)
class PubSubWS(WS):
'''A :class:`.WS` handler with a publish-subscribe handler
'''
client = PubSubClient
def __init__(self, pubsub, channel):
self.pubsub = pubsub
self.channel = channel
def on_open(self, websocket):
'''When a new websocket connection is established it creates a
new :class:`ChatClient` and adds it to the set of clients of the
:attr:`pubsub` handler.'''
self.pubsub.add_client(self.client(websocket, self.channel))