Skip to content

Commit

Permalink
Support all async modes when app.debug is set
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Sep 21, 2015
1 parent 4ddde39 commit d79e27b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 22 deletions.
10 changes: 7 additions & 3 deletions example/app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/usr/bin/env python

# set this variable to "threading", "eventlet" or "gevent" to test the
# different async modes
async_mode = 'threading'

if async_mode == 'eventlet':
Expand All @@ -9,7 +13,7 @@

import time
from threading import Thread
from flask import Flask, render_template, session
from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect

Expand Down Expand Up @@ -104,8 +108,8 @@ def test_connect():

@socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected')
print('Client disconnected', request.sid)


if __name__ == '__main__':
socketio.run(app)
socketio.run(debug=True)
66 changes: 47 additions & 19 deletions flask_socketio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import socketio
import flask
from werkzeug.debug import DebuggedApplication
from werkzeug.serving import run_with_reloader

from .test_client import SocketIOTestClient

Expand Down Expand Up @@ -258,24 +260,35 @@ def close_room(self, room, namespace=None):
def run(self, app=None, host=None, port=None, **kwargs):
"""Run the SocketIO web server.
:param app: The Flask application instance.
:param app: The Flask application instance. This argument is kept for
legacy reasons, it can be omitted.
:param host: The hostname or IP address for the server to listen on.
Defaults to 127.0.0.1.
:param port: The port number for the server to listen on. Defaults to
5000.
:param debug: ``True`` to start the server in debug mode, ``False`` to
start in normal mode.
:param use_reloader: ``True`` to enable the Flask reloader, ``False``
to disable it.
:param extra_files: A list of additional files that the Flask
reloader should watch. Defaults to ``None``
:param log_output: If ``True``, the server logs all incomming
connections. If ``False`` logging is disabled.
Defaults to ``True`` in debug mode, ``False``
otherwise.
in normal mode. Unused wheb the threading async
mode is used.
:param resource: The SocketIO resource name. Defaults to
``'socket.io'``. Leave this as is unless you know what
you are doing.
:param kwargs: Socket.IO and Engine.IO server options. See the
constructor of this class for the list of available
options.
"""
if app is None:
app = self.app
else:
self.app = app

if host is None:
host = '127.0.0.1'
if port is None:
Expand All @@ -285,26 +298,24 @@ def run(self, app=None, host=None, port=None, **kwargs):
else:
port = 5000

if app is None:
app = self.app
else:
self.app = app

self.server_options.update(kwargs)
test_mode = self.server_options.pop('test_mode', False)
log_output = self.server_options.pop('log_output', app.debug)
use_reloader = self.server_options.pop('use_reloader', app.debug)
debug = self.server_options.pop('debug', app.debug)
log_output = self.server_options.pop('log_output', debug)
use_reloader = self.server_options.pop('use_reloader', debug)
extra_files = kwargs.pop('extra_files', None)
resource = self.server_options.pop('resource', 'socket.io')
if resource.startswith('/'):
resource = resource[1:]
if app.debug:
self.server_options['async_mode'] = 'threading'

self.server = socketio.Server(**self.server_options)
for namespace in self.handlers.keys():
for message, handler in self.handlers[namespace].items():
self.server.on(message, handler, namespace=namespace)

app.debug = debug
if app.debug and self.server.eio.async_mode != 'threading':
app.wsgi_app = DebuggedApplication(app.wsgi_app, evalex=True)
app.wsgi_app = socketio.Middleware(self.server, app.wsgi_app,
socketio_path=resource)

Expand All @@ -313,9 +324,15 @@ def run(self, app=None, host=None, port=None, **kwargs):
app.run(host=host, port=port, threaded=True,
use_reloader=use_reloader)
elif self.server.eio.async_mode == 'eventlet':
import eventlet
eventlet.wsgi.server(eventlet.listen((host, port)), app,
log_output=log_output, **kwargs)
def run_server():
import eventlet
eventlet.wsgi.server(eventlet.listen((host, port)), app,
log_output=log_output, **kwargs)

if use_reloader:
run_with_reloader(run_server, extra_files=extra_files)
else:
run_server()
elif self.server.eio.async_mode == 'gevent':
from gevent import pywsgi
try:
Expand All @@ -328,12 +345,23 @@ def run(self, app=None, host=None, port=None, **kwargs):
if not log_output:
log = None
if websocket:
pywsgi.WSGIServer((host, port), app,
handler_class=WebSocketHandler,
log=log).serve_forever()
server = pywsgi.WSGIServer((host, port), app,
handler_class=WebSocketHandler,
log=log)
else:
server = pywsgi.WSGIServer((host, port), app, log=log)

if use_reloader:
# monkey patching is required by the reloader
from gevent import monkey
monkey.patch_all()

def run_server():
server.serve_forever()

run_with_reloader(run_server, extra_files=extra_files)
else:
pywsgi.WSGIServer((host, port), app,
log=log).serve_forever()
server.serve_forever()

def test_client(self, app, namespace=None):
"""Return a simple SocketIO client that can be used for unit tests."""
Expand Down

0 comments on commit d79e27b

Please sign in to comment.