gevent-socketio not using my @app.route endpoint for socketio
flask, python, socket.io, web, websocket
Solution
The weird behavior is because of this line:
dapp = werkzeug.debug.DebuggedApplication(app, evalex = True)
Socketio and the werkzeug debugger don't work together. There is already an open issue about this see: https://github.com/abourget/gevent-socketio/issues/114
But you can work around it by making a custom debugger class.
from werkzeug.debug import DebuggedApplication
class MyDebuggedApplication(DebuggedApplication):
def __call__(self, environ, start_response):
# check if websocket call
if "wsgi.websocket" in environ and not environ["wsgi.websocket"] is None:
# a websocket call, no debugger ;)
return self.app(environ, start_response)
# else go on with debugger
return DebuggedApplication.__call__(self, environ, start_response)
# remember to call the overwritten debugger in your run_dev_server() function
dapp = MyDebuggedApplication(app, evalex = True)
The patch relies on the environment-key wsgi.websocket, which only seems to be present in websocket calls. Be careful, I haven't put much thought into that, there are might be other issues.
Problem
I am using Flask together with gevent-socketio: ``` $ cat requirements.txt Flask==0.10.1 Jinja2==2.7.1 MarkupSafe==0.18 Werkzeug==0.9.3 argparse==1.2.1 gevent==0.13.8 gevent-socketio==0.3.5-rc2 gevent-websocket==0.3.6 greenlet==0.4.1 itsdangerous==0.23 wsgiref==0.1.2 ``` I'm using a pretty standard setup to start the server: ``` #Called from __main__ def run_dev_server(): app.debug = True port = 5000 dapp = werkzeug.debug.DebuggedApplication(app, evalex = True) SocketIOServer(('', port), dapp, resource="socket.io").serve_forever() ``` And a pretty standard hook for my SocketIO namespace: ``` @app.route('/socket.io/<path:rest>') def push_stream(rest): print 'ws connect', rest try: socketio.socketio_manage(request.environ, {'/join_notification': JoinsNamespace}, request) except Exception as e: app.logger.error("Exception while handling socketio connection", exc_info=True) return flask.Response() ``` However, I'm having problems where 'connect' events aren't being fired on the client. After a little digging, I realized that even though I was getting `127.0.0.1 - - [2013-08-19 12:53:57] "GET /socket.io/1/websocket/170191232666 HTTP/1.1" 101 - -` messages in the output, I wasn't getting the `ws connect` message (while other print statements in the code were working fine). I commented out that endpoint, and sure enough it's not even being called. That would explain why my namespace isn't being used. But why? Am I registering my namespace wrong? `print app.url_map` yields: ``` Map([<Rule '/' (HEAD, OPTIONS, GET) -> root>, <Rule '/socket.io/<rest>' (HEAD, OPTIONS, GET) -> push_stream>, <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>]) ``` So nothing out of the ordinary. Edit: The client code: ``` socket = io.connect('/join_notification') console.log(socket) socket.on('connect', function() { console.log('connected to websocket') socket.emit('login', {'name': data['name']}) }) socket.on('disconnect', function() { console.log('d/c\'d from websocket') }) socket.on('join_error', function() { ... }) socket.on('join_success', function(data){ ... }) socket.on('join', function(data) { ... }) ```