Cullen S
Cullen S

Reputation: 155

Shut down Flask SocketIO Server

For circumstances outside of my control, I need to use the Flask server to serve basic html files, the Flask SocketIO wrapper to provide a web socket interface between any clients and the server. The async_mode has to be threading instead of gevent or eventlet, I understand that it is less efficient to use threading, but I can't use the other two frameworks.

In my unit tests, I need to shut down and restart the web socket server. When I attempt to shut down the server, I get the RunTimeError 'Cannot stop unknown web server.' This is because the function werkzeug.server.shutdown is not found in the Flask Request Environment flask.request.environ object.

Here is how the server is started.

SERVER = flask.Flask(__name__)

WEBSOCKET = flask_socketio.SocketIO(SERVER, async_mode='threading')

WEBSOCKET.run(SERVER, host='127.0.0.1', port=7777)

Here is the short version of how I'm attempting to shut down the server.

client = WEBSOCKET.test_client(SERVER)

@WEBSOCKET.on('kill')
def killed():
    WEBSOCKET.stop()

try:
    client.emit('kill')
except:
    pass

The stop method must be called from within a flask request context, hence the weird kill event callback. Inside the stop method, the flask.request.environ has the value

'CONTENT_LENGTH' (40503696) = {str} '0'
'CONTENT_TYPE' (60436576) = {str} ''
'HTTP_HOST' (61595248) = {str} 'localhost'
'PATH_INFO' (60437104) = {str} '/socket.io'
'QUERY_STRING' (60327808) = {str} ''
'REQUEST_METHOD' (40503648) = {str} 'GET'
'SCRIPT_NAME' (60437296) = {str} ''
'SERVER_NAME' (61595296) = {str} 'localhost'
'SERVER_PORT' (61595392) = {str} '80'
'SERVER_PROTOCOL' (65284592) = {str} 'HTTP/1.1'
'flask.app' (65336784) = {Flask} <Flask 'server'>
'werkzeug.request' (60361056) = {Request} <Request 'http://localhost/socket.io' [GET]>
'wsgi.errors' (65338896) = {file} <open file '<stderr>', mode 'w' at 0x0000000001C92150>
'wsgi.input' (65338848) = {StringO} <cStringIO.StringO object at 0x00000000039902D0>
'wsgi.multiprocess' (65369288) = {bool} False
'wsgi.multithread' (65369232) = {bool} False
'wsgi.run_once' (65338944) = {bool} False
'wsgi.url_scheme' (65338800) = {str} 'http'
'wsgi.version' (65338752) = {tuple} <type 'tuple'>: (1, 0)

My question is, how do I set up the Flask server to have the werkzeug.server.shutdownmethod available inside the flask request contexts?

Also this is using Python 2.7

Upvotes: 2

Views: 2858

Answers (1)

Miguel Grinberg
Miguel Grinberg

Reputation: 67479

I have good news for you, the testing environment does not use a real server, in that context the client and the server run inside the same process, so the communication between them does not go through the network as it does when you run things for real. Really in this situation there is no server, so there's nothing to stop.

It seems you are starting a real server, though. For unit tests, that server is not used, all you need are your unit tests which import the application and then use a test client to issue socket.io events. I think all you need to do is just not start the server, the unit tests should run just fine without it if all you use is the test client as you show above.

Upvotes: 2

Related Questions