2525 request's processing. Enable that tool at
2626 any path you wish to handle as a WebSocket
2727 handler.
28-
28+
2929 * WebSocketPlugin: The plugin tracks the instanciated web socket handlers.
3030 It also cleans out websocket handler which connection
3131 have been closed down. The websocket connection then
3232 runs in its own thread that this plugin manages.
33-
33+
3434Simple usage example:
3535
3636.. code-block:: python
3939 import cherrypy
4040 from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
4141 from ws4py.websocket import EchoWebSocket
42-
42+
4343 cherrypy.config.update({'server.socket_port': 9000})
4444 WebSocketPlugin(cherrypy.engine).subscribe()
4545 cherrypy.tools.websocket = WebSocketTool()
@@ -52,7 +52,7 @@ def index(self):
5252 @cherrypy.expose
5353 def ws(self):
5454 pass
55-
55+
5656 cherrypy.quickstart(Root(), '/', config={'/ws': {'tools.websocket.on': True,
5757 'tools.websocket.handler_cls': EchoWebSocket}})
5858
@@ -97,7 +97,8 @@ def _setup(self):
9797 hooks .attach ('on_end_request' , self .start_handler ,
9898 priority = 70 )
9999
100- def upgrade (self , protocols = None , extensions = None , version = WS_VERSION , handler_cls = WebSocket ):
100+ def upgrade (self , protocols = None , extensions = None , version = WS_VERSION ,
101+ handler_cls = WebSocket , heartbeat_freq = None ):
101102 """
102103 Performs the upgrade of the connection to the WebSocket
103104 protocol.
@@ -113,13 +114,13 @@ def upgrade(self, protocols=None, extensions=None, version=WS_VERSION, handler_c
113114 """
114115 request = cherrypy .serving .request
115116 request .process_request_body = False
116-
117+
117118 ws_protocols = None
118119 ws_location = None
119120 ws_version = version
120121 ws_key = None
121122 ws_extensions = []
122-
123+
123124 if request .method != 'GET' :
124125 raise HandshakeError ('HTTP method must be a GET' )
125126
@@ -131,25 +132,25 @@ def upgrade(self, protocols=None, extensions=None, version=WS_VERSION, handler_c
131132 if expected_value not in actual_value :
132133 raise HandshakeError ('Illegal value for header %s: %s' %
133134 (key , actual_value ))
134-
135+
135136 version = request .headers .get ('Sec-WebSocket-Version' )
136137 supported_versions = ', ' .join ([str (v ) for v in ws_version ])
137138 version_is_valid = False
138139 if version :
139140 try : version = int (version )
140141 except : pass
141142 else : version_is_valid = version in ws_version
142-
143+
143144 if not version_is_valid :
144145 cherrypy .response .headers ['Sec-WebSocket-Version' ] = supported_versions
145146 raise HandshakeError ('Unhandled or missing WebSocket version' )
146-
147+
147148 key = request .headers .get ('Sec-WebSocket-Key' )
148149 if key :
149150 ws_key = base64 .b64decode (enc (key ))
150151 if len (ws_key ) != 16 :
151152 raise HandshakeError ("WebSocket key's length is invalid" )
152-
153+
153154 protocols = protocols or []
154155 subprotocols = request .headers .get ('Sec-WebSocket-Protocol' )
155156 if subprotocols :
@@ -166,7 +167,7 @@ def upgrade(self, protocols=None, extensions=None, version=WS_VERSION, handler_c
166167 ext = ext .strip ()
167168 if ext in exts :
168169 ws_extensions .append (ext )
169-
170+
170171 location = []
171172 include_port = False
172173 if request .scheme == "https" :
@@ -199,8 +200,9 @@ def upgrade(self, protocols=None, extensions=None, version=WS_VERSION, handler_c
199200 addr = (request .remote .ip , request .remote .port )
200201 ws_conn = get_connection (request .rfile .rfile )
201202 request .ws_handler = handler_cls (ws_conn , ws_protocols , ws_extensions ,
202- request .wsgi_environ .copy ())
203-
203+ request .wsgi_environ .copy (),
204+ heartbeat_freq = heartbeat_freq )
205+
204206 def complete (self ):
205207 """
206208 Sets some internal flags of CherryPy so that it
@@ -216,7 +218,7 @@ def cleanup_headers(self):
216218 response = cherrypy .response
217219 if not response .header_list :
218220 return
219-
221+
220222 headers = response .header_list [:]
221223 for (k , v ) in headers :
222224 if k [:7 ] == 'Sec-Web' :
@@ -226,7 +228,7 @@ def cleanup_headers(self):
226228 def start_handler (self ):
227229 """
228230 Runs at the end of the request processing by calling
229- the opened method of the handler.
231+ the opened method of the handler.
230232 """
231233 request = cherrypy .request
232234 if not hasattr (request , 'ws_handler' ):
@@ -240,9 +242,9 @@ def start_handler(self):
240242 # By doing this we detach the socket from
241243 # the CherryPy stack avoiding memory leaks
242244 detach_connection (request .rfile .rfile )
243-
245+
244246 cherrypy .engine .publish ('handle-websocket' , ws_handler , addr )
245-
247+
246248 def _set_internal_flags (self ):
247249 """
248250 CherryPy has two internal flags that we are interested in
@@ -286,7 +288,7 @@ def start(self):
286288 self .bus .subscribe ('stop' , self .cleanup )
287289 self .bus .subscribe ('handle-websocket' , self .handle )
288290 self .bus .subscribe ('websocket-broadcast' , self .broadcast )
289-
291+
290292 def stop (self ):
291293 cherrypy .log ("Terminating WebSocket processing" )
292294 self .bus .unsubscribe ('main' , self .monitor )
@@ -316,7 +318,7 @@ def monitor(self):
316318 handlers = list (self .pool .keys ())
317319 else :
318320 handlers = self .pool .keys ()[:]
319-
321+
320322 for handler in handlers :
321323 if handler .terminated :
322324 th , addr = self .pool [handler ]
@@ -350,14 +352,14 @@ def broadcast(self, message, binary=False):
350352 ws_handler .send (message , binary )
351353 except :
352354 cherrypy .log (traceback = True )
353-
355+
354356if __name__ == '__main__' :
355357 import random
356358 cherrypy .config .update ({'server.socket_host' : '127.0.0.1' ,
357359 'server.socket_port' : 9000 })
358360 WebSocketPlugin (cherrypy .engine ).subscribe ()
359361 cherrypy .tools .websocket = WebSocketTool ()
360-
362+
361363 class Root (object ):
362364 @cherrypy .expose
363365 @cherrypy .tools .websocket (on = False )
@@ -369,13 +371,13 @@ def ws(self):
369371 $(document).ready(function() {
370372 var ws = new WebSocket('ws://192.168.0.10:9000/');
371373 ws.onmessage = function (evt) {
372- $('#chat').val($('#chat').val() + evt.data + '\\ n');
374+ $('#chat').val($('#chat').val() + evt.data + '\\ n');
373375 };
374376 ws.onopen = function() {
375377 ws.send("Hello there");
376378 };
377379 ws.onclose = function(evt) {
378- $('#chat').val($('#chat').val() + 'Connection closed by server: ' + evt.code + ' \" ' + evt.reason + '\" \\ n');
380+ $('#chat').val($('#chat').val() + 'Connection closed by server: ' + evt.code + ' \" ' + evt.reason + '\" \\ n');
379381 };
380382 $('#chatform').submit(function() {
381383 ws.send('%(username)s: ' + $('#message').val());
@@ -399,6 +401,6 @@ def ws(self):
399401 @cherrypy .expose
400402 def index (self ):
401403 cherrypy .log ("Handler created: %s" % repr (cherrypy .request .ws_handler ))
402-
404+
403405 cherrypy .quickstart (Root (), '/' , config = {'/' : {'tools.websocket.on' : True ,
404406 'tools.websocket.handler_cls' : EchoWebSocketHandler }})
0 commit comments