The class * RequestHandler* (tornado 3.1.1) has e new function *
_When_complete* that is called by the function *_execute*.
------------------------------------------------------vvvvv--------------------------------------------------------------
def _execute(self, transforms, *args, **kwargs):
"""Executes this request with the given output transforms."""
self._transforms = transforms
try:
if self.request.method not in self.SUPPORTED_METHODS:
raise HTTPError(405)
self.path_args = [self.decode_argument(arg) for arg in args]
self.path_kwargs = dict((k, self.decode_argument(v, name=k))
for (k, v) in kwargs.items())
# If XSRF cookies are turned on, reject form submissions without
# the proper cookie
if self.request.method not in ("GET", "HEAD", "OPTIONS") and \
self.application.settings.get("xsrf_cookies"):
self.check_xsrf_cookie()
self._when_complete(self.prepare(), self._execute_method)
except Exception as e:
self._handle_request_exception(e)
def _when_complete(self, result, callback):
try:
if result is None:
callback()
elif isinstance(result, Future):
if result.done():
if result.result() is not None:
raise ValueError('Expected None, got %r' % result)
callback()
else:
# Delayed import of IOLoop because it's not available
# on app engine
from tornado.ioloop import IOLoop
IOLoop.current().add_future(
result, functools.partial(self._when_complete,
callback=callback))
else:
raise ValueError("Expected Future or None, got %r" % result)
except Exception as e:
self._handle_request_exception(e)
----------------------------------------------^^^^^
---------------------------------------------------------------------
I modified websocket_messaging (in red) and is now working with the
tornado 3.1.1
(tonado 3.0 too), but do not know if you are having the exact result you
had in previous versions.
------------------------------------------vvvvvvv--------------------------------------------------------------------
#!/usr/bin/env python
"""
This file is part of the web2py Web Framework
Copyrighted by Massimo Di Pierro <[email protected]>
License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
Attention: Requires Chrome or Safari. For IE of Firefox you need
https://github.com/gimite/web-socket-js
1) install tornado (*r**equires Tornado 3.0 or late*r)
easy_install tornado
2) start this app:
python gluon/contrib/websocket_messaging.py -k mykey -p 8888
3) from any web2py app you can post messages with
from gluon.contrib.websocket_messaging import websocket_send
websocket_send('http://127.0.0.1:8888','Hello World','mykey','mygroup')
4) from any template you can receive them with
<script>
$(document).ready(function(){
if(!*$.web2py.*web2py_websocket('ws://127.0.0.1:8888/realtime/mygroup
',function(e){alert(e.data)}))
alert("html5 websocket not supported by your browser, try Google
Chrome");
});
</script>
When the server posts a message, all clients connected to the page will
popup an alert message
Or if you want to send json messages and store evaluated json in a var
called data:
<script>
$(document).ready(function(){
var data;
*$.web2py*.web2py_websocket('ws://127.0.0.1:8888/realtime/mygroup
',function(e){data=eval('('+e.data+')')});
});
</script>
- All communications between web2py and websocket_messaging will be
digitally signed with hmac.
- All validation is handled on the web2py side and there is no need to
modify websocket_messaging.py
- Multiple web2py instances can talk with one or more websocket_messaging
servers.
- "ws://127.0.0.1:8888/realtime/" must be contain the IP of the
websocket_messaging server.
- Via group='mygroup' name you can support multiple groups of clients
(think of many chat-rooms)
Here is a complete sample web2py action:
def index():
form=LOAD('default','ajax_form',ajax=True)
script=SCRIPT('''
jQuery(document).ready(function(){
var callback=function(e){alert(e.data)};
if(!*$.web2py.*web2py_websocket('ws://
127.0.0.1:8888/realtime/mygroup',callback))
alert("html5 websocket not supported by your browser, try
Google Chrome");
});
''')
return dict(form=form, script=script)
def ajax_form():
form=SQLFORM.factory(Field('message'))
if form.accepts(request,session):
from gluon.contrib.websocket_messaging import websocket_send
websocket_send(
'http://127.0.0.1:8888',form.vars.message,'mykey','mygroup')
return form
Acknowledgements:
Tornado code inspired by
http://thomas.pelletier.im/2010/08/websocket-tornado-redis/
"""
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import hmac
import sys
import optparse
import urllib
import time
listeners = {}
names = {}
tokens = {}
def websocket_send(url, message, hmac_key=None, group='default'):
sig = hmac_key and hmac.new(hmac_key, message).hexdigest() or ''
params = urllib.urlencode(
{'message': message, 'signature': sig, 'group': group})
f = urllib.urlopen(url, params)
data = f.read()
f.close()
return data
class PostHandler(tornado.web.RequestHandler):
"""
only authorized parties can post messages
"""
def post(self):
if hmac_key and not 'signature' in self.request.arguments:
*return None*
if 'message' in self.request.arguments:
message = self.request.arguments['message'][0]
group = self.request.arguments.get('group', ['default'])[0]
print '%s:MESSAGE to %s:%s' % (time.time(), group, message)
if hmac_key:
signature = self.request.arguments['signature'][0]
if not hmac.new(hmac_key, message).hexdigest() == signature:
*return None*
for client in listeners.get(group, []):
client.write_message(message)
* return None*
class TokenHandler(tornado.web.RequestHandler):
"""
if running with -t post a token to allow a client to join using the
token
the message here is the token (any uuid)
allows only authorized parties to joins, for example, a chat
"""
def post(self):
if hmac_key and not 'message' in self.request.arguments:
*return None*
if 'message' in self.request.arguments:
message = self.request.arguments['message'][0]
if hmac_key:
signature = self.request.arguments['signature'][0]
if not hmac.new(hmac_key, message).hexdigest() == signature:
*return None*
tokens[message] = None
*return None*
class DistributeHandler(tornado.websocket.WebSocketHandler):
def open(self, params):
group, token, name = params.split('/') + [None, None]
self.group = group or 'default'
self.token = token or 'none'
self.name = name or 'anonymous'
# only authorized parties can join
if DistributeHandler.tokens:
if not self.token in tokens or not token[self.token] is None:
self.close()
else:
tokens[self.token] = self
if not self.group in listeners:
listeners[self.group] = []
# notify clients that a member has joined the groups
for client in listeners.get(self.group, []):
client.write_message('+' + self.name)
listeners[self.group].append(self)
names[self] = self.name
print '%s:CONNECT to %s' % (time.time(), self.group)
def on_message(self, message):
pass
def on_close(self):
if self.group in listeners:
listeners[self.group].remove(self)
del names[self]
# notify clients that a member has left the groups
for client in listeners.get(self.group, []):
client.write_message('-' + self.name)
print '%s:DISCONNECT from %s' % (time.time(), self.group)
if __name__ == "__main__":
usage = __doc__
version = ""
parser = optparse.OptionParser(usage, None, optparse.Option, version)
parser.add_option('-p',
'--port',
default='8888',
dest='port',
help='socket')
parser.add_option('-l',
'--listen',
default='0.0.0.0',
dest='address',
help='listener address')
parser.add_option('-k',
'--hmac_key',
default='',
dest='hmac_key',
help='hmac_key')
parser.add_option('-t',
'--tokens',
action='store_true',
default=False,
dest='tokens',
help='require tockens to join')
(options, args) = parser.parse_args()
hmac_key = options.hmac_key
DistributeHandler.tokens = options.tokens
urls = [
(r'/', PostHandler),
(r'/token', TokenHandler),
(r'/realtime/(.*)', DistributeHandler)]
application = tornado.web.Application(urls, auto_reload=True)
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(int(options.port), address=options.address)
tornado.ioloop.IOLoop.instance().start()
-------------------------------------------------^^^^^^^--------------------------------------------------------------
I await confirmation of a more experienced programmer. Because I'm still
learning.
2013/10/7 Junior Phanter <[email protected]>
> I'll try to help. It will be an honor for me.
>
>
> 2013/10/7 Massimo Di Pierro <[email protected]>
>
>> Can you help us find out why Tornado 31. does not work?
>>
>>
>> On Sunday, 6 October 2013 21:24:29 UTC-5, Junior Phanter wrote:
>>
>>> Sorry my bad english,
>>>
>>> Analyzing the web2py_websocket inside web2py.js. I noticed that when I
>>> used:
>>>
>>> <script>
>>> $(document).ready(function(){
>>> var data;
>>>
>>> web2py_websocket('ws://127.0.**0.1:8888/realtime/mygroup<http://127.0.0.1:8888/realtime/mygroup>',
>>> function(e){data=eval('('+e.**data+')')});
>>> });
>>> </script>
>>>
>>>
>>> the browser console accused the "web2py_websocket was not a function", so
>>> I changed the code to:
>>>
>>> <script>
>>> $(document).ready(function(){
>>> var data;
>>> $.web2py.web2py_websocket('ws:**//127.0.0.1:8888/realtime/**
>>> mygroup <http://127.0.0.1:8888/realtime/mygroup>',
>>> function(e){data=eval('('+e.**data+')')});
>>> });
>>> </script>
>>>
>>> worked perfectly!
>>>
>>>
>>> I changed it to Tornado 3.0 (Tornado 3.1.1 not work) and web2py 2.7.1.
>>>
>>>
>>> 2013/10/4 Junior Phanter <[email protected]>
>>>
>>>> greetings ,
>>>> sorry my bad english , I 'm trying to implement a chat using the
>>>> tornado and websocket_messaging.py , but I'm having trouble hearing the
>>>> tornado server . the server receives the tornado MESSAGES using :
>>>>
>>>> websocket_send ( ' http://127.0.0.1:8888 ', ' Hello World ', ' mykey
>>>> ', ' mygroup ' )
>>>>
>>>> but the script :
>>>> ------------------------------**------------------------------**-----
>>>> <script>
>>>> $(document).ready(function(){
>>>> var data;
>>>>
>>>> web2py_websocket('ws://127.0.**0.1:8888/realtime/mygroup<http://127.0.0.1:8888/realtime/mygroup>
>>>> ',**function(e){data=eval('('+e.**data+')')});
>>>> });
>>>> </script>
>>>> ------------------------------**------------------------------**
>>>> -------------
>>>> does not capture the listener .
>>>>
>>>> I tested the application that comes as an example within the
>>>> websocket_messaging.py and neither worked .
>>>>
>>>> --------------------- exemplo dentro do websocket_messaging.py
>>>> --------------------------
>>>>
>>>> Here is a complete sample web2py action:
>>>>
>>>> def index():
>>>> form=LOAD('default','ajax_**form',ajax=True)
>>>> script=SCRIPT('''
>>>> jQuery(document).ready(**function(){
>>>> var callback=function(e){alert(e.**data)};
>>>> if(!web2py_websocket('ws://127**
>>>> .0.0.1:8888/realtime/mygroup <http://127.0.0.1:8888/realtime/mygroup>',
>>>> **callback))
>>>> alert("html5 websocket not supported by your browser,
>>>> try Google Chrome");
>>>> });
>>>> ''')
>>>> return dict(form=form, script=script)
>>>>
>>>> def ajax_form():
>>>> form=SQLFORM.factory(Field('**message'))
>>>> if form.accepts(request,session):
>>>> from gluon.contrib.websocket_**messaging import
>>>> websocket_send
>>>> websocket_send(
>>>> 'http://127.0.0.1:8888',form.**
>>>> vars.message,'mykey','mygroup'**)
>>>> return form
>>>>
>>>> ------------------------------**------------------------------**
>>>> ------------------------------**-----------
>>>>
>>>>
>>>>
>>>> I'm using the Tornado 2.1 and 2.6.4 web2py
>>>>
>>>> --
>>>> Resources:
>>>> - http://web2py.com
>>>> - http://web2py.com/book (Documentation)
>>>> - http://github.com/web2py/**web2py
>>>> <http://github.com/web2py/web2py>(Source code)
>>>> -
>>>> https://code.google.com/p/**web2py/issues/list<https://code.google.com/p/web2py/issues/list>(Report
>>>> Issues)
>>>> ---
>>>> You received this message because you are subscribed to the Google
>>>> Groups "web2py-users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to web2py+un...@**googlegroups.com.
>>>>
>>>> For more options, visit
>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>> .
>>>>
>>>
>>> --
>> Resources:
>> - http://web2py.com
>> - http://web2py.com/book (Documentation)
>> - http://github.com/web2py/web2py (Source code)
>> - https://code.google.com/p/web2py/issues/list (Report Issues)
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "web2py-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>
>
--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.