Search code examples
pythonsocket.iogeventgevent-socketio

gevent-socketio how to originate messages from server


This is my code:

class FirstNamespace(BaseNamespace):
    def on_some_event(self, msg):
        self.emit('ok '+msg)

@app.route('/socket.io/<path:remaining>')  # socket.io endpoint
def socketio_withpath(remaining):
    socketio_manage(request.environ,
                    {'/channel1': FirstNamespace}
    return 'ok'

@app.route('/dosomething/', methods=['POST'])  # simple http endpoint
def dosomething():
    data = request.form
    # ...
    # some code that triggers self.emit from within FirstNamespace 
    # ...
    return 'data processed'

I can happily send socket messages from frontend, they get processed and I receive replies from on_some_event method.

The problem is, I can only receive a message if I first send one myself.

But how can I start receiving messages without being the first one to talk?

For example, if someone sends a POST to the /dosomething/ endpoint, how can it trigger an emit to my client websocket?

--

I can do this in flask-socketio but it does too much magic to my taste. Is there a lower level implementation for this?


Solution

  • You have to collect all channel1-Connections in a set, then you can send messages to all connections:

    from weakref import WeakSet
    
    class FirstNamespace(BaseNamespace):
        connections = WeakSet()
    
        def initialize(self):
            self.connections.add(self)
    
        def on_some_event(self, msg):
            self.emit('ok '+msg)
    
    @app.route('/socket.io/<path:remaining>')  # socket.io endpoint
    def socketio_withpath(remaining):
        socketio_manage(request.environ,
                        {'/channel1': FirstNamespace}
        return 'ok'
    
    @app.route('/dosomething/', methods=['POST'])  # simple http endpoint
    def dosomething():
        data = request.form
        for conn in FirstNamespace.connections:
            conn.emit("response_channel", data)
        return 'data processed'