Code Monkey home page Code Monkey logo

Comments (15)

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024 1

Try the main branch of flask-socketio and let me know if that works better.

Note that your catch-all handler should be as follows:

@socketio.on('in', namespace='*')
def on_in_star(data):
    print(f"--- IN; catchall ns = {request.namespace}, {data}\n")

In Flask-SocketIO you do not need to add the namespace as an argument, because you always get it in request.namespace.

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024 1

Worked! Looks like it's doing everything I expect now, thanks!

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

Monkey patch:

import types
old_geh = socketio.server._get_event_handler
socketio.server.old_geh = socketio.server._get_event_handler
def new_geh(self, event, namespace, *args):
    sys.stderr.write(f"XXX e:{event} ns:{namespace}\n")
    h, a = self.old_geh(event, namespace, *args)
    sys.stderr.write(f">>> h:{h} a:{a}\n")
    return h, a
socketio.server._get_event_handler = types.MethodType(new_geh, socketio.server)

stderr output:

XXX e:connect ns:/
>>> h:<function on_connect at 0x7fb810513370> a:(...)

from flask-socketio.

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024

The connect and disconnect handlers are not dispatched to catch-all handlers, only user-defined events are.

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

Hm is that intentional, or can they also be enabled? Without a connect catch-all, it doesn't seem like dynamic / arbitrary namespaces would be possible, i.e. all allowable namespaces would have to be explicitly assigned to a handler.


That said, something weird is still going on (which is what prompted my other post miguelgrinberg/python-socketio#1334 in the first place): I've pared it down to this minimal server code. If a client connects on the default namespace then sends an "in" event , it gets lost with:

from flask import Flask, render_template, request 
from flask_socketio import SocketIO
import sys


app = Flask(__name__)
socketio = SocketIO(app, namespaces="*")

@app.route('/')
def root():
    return render_template('index.html')

@socketio.on('connect') 
def on_connect(auth):
    sys.stderr.write(f"*** IN CONNECT w/ default ns\n")

@socketio.on('in', namespace='*')
def on_in_star(ns, data):
    sys.stderr.write(f"--- IN; catchall ns = {ns}, {data}\n")

if __name__ == '__main__':
    socketio.run(app, debug=True)

The ns catchall does not get triggered. But if I add a ns-specific handler:

@socketio.on('in', namespace='/')
def on_in(data):
    sys.stderr.write(f"/// IN; ns = '/', data = {data}\n")

that one does successfully get triggered.

For completeness, index.html:

<html>
  <head>
    <script src="/static/js/socket.io.min.js"></script>
  </head>

  <body>
    <script>
        const socket = io();

        socket.on('connect', function() {
            console.log("Connected to server, emitting 'hello' to 'in'");
            socket.emit('in', 'hello')
        });
    </script>
  </body>
</html>

from flask-socketio.

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024

So your client is sending an event on a namespace it did not connect to? That does not work, the client must connect to the namespace(s) it wants to use.

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024
  • The client connects to the default namespace (i.e. "/")
    • The connection succeeds and the ns-specific connection handler is called.
  • The client sends a message to an event on the connected sio (i.e. namespace = "/"). Either:
    • The message gets successfully handled if there is a ns-specific event handler, or
    • The message gets dropped if there is only a ns catch-all handler (and no ns-specific event handler). The catch-all handler does not get called. This is the bug.

(I'll split out the other issue into its own thread.)

from flask-socketio.

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024

How is this different from the situation described in miguelgrinberg/python-socketio#1334, which we agreed that is working correctly?

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

Yeah we agreed that it should work... but it doesn't. Again, here is a MWE, now all contained in a single file:

from flask import Flask
from flask_socketio import SocketIO


app = Flask(__name__)
socketio = SocketIO(app, namespaces="*", logger=True, engineio_logger=True)

@app.route('/')
def root():
    return '''<!DOCTYPE html>
<html>
  <head><script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script></head>
  <body><script>
        const socket = io();
        socket.on('connect', function() {
            socket.emit('in', 'hello')
        });
  </script></body>
</html>
'''

@socketio.on('connect')
def on_connect(auth):
    print(f"*** CONNECT; default ns\n")

@socketio.on('in', namespace='*')
def on_in_star(ns, data):
    print(f"--- IN; catchall ns = {ns}, {data}\n")

if __name__ == '__main__':
    socketio.run(app, debug=True)

If everything was working as intended, we would expect to see both print statements execute, i.e. if we see *** CONNECT; default ns then we should also see --- IN; catchall ns = /, hello. But we don't:

8S2llN_8QFMwcWC9AAAA: Sending packet OPEN data {'sid': '8S2llN_8QFMwcWC9AAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000}
127.0.0.1 - - [08/May/2024 02:09:04] "GET /socket.io/?EIO=4&transport=polling&t=OzNTgOA HTTP/1.1" 200 -
8S2llN_8QFMwcWC9AAAA: Received packet MESSAGE data 0
*** CONNECT; default ns

8S2llN_8QFMwcWC9AAAA: Sending packet MESSAGE data 0{"sid":"qhmheUkfz-IN1VcHAAAB"}
127.0.0.1 - - [08/May/2024 02:09:04] "POST /socket.io/?EIO=4&transport=polling&t=OzNTgOR&sid=8S2llN_8QFMwcWC9AAAA HTTP/1.1" 200 -
8S2llN_8QFMwcWC9AAAA: Received request to upgrade to websocket
127.0.0.1 - - [08/May/2024 02:09:04] "GET /socket.io/?EIO=4&transport=polling&t=OzNTgOy&sid=8S2llN_8QFMwcWC9AAAA HTTP/1.1" 200 -
127.0.0.1 - - [08/May/2024 02:09:04] "GET /socket.io/?EIO=4&transport=polling&t=OzNTgOy.0&sid=8S2llN_8QFMwcWC9AAAA HTTP/1.1" 200 -
8S2llN_8QFMwcWC9AAAA: Upgrade to websocket successful
8S2llN_8QFMwcWC9AAAA: Received packet MESSAGE data 2["in","hello"]
received event "in" from qhmheUkfz-IN1VcHAAAB [/]

The received event should get dispatched to the in handler in the catch-all namespace... but it does not.

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

@miguelgrinberg Could you make a new release with this commit to save having to pip install from git? Thanks!

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

Also, there may need to be a similar fix to allow catch-all event handling? I don't think I can successfully do a

@socketio.on('*')

(but I haven't tried very much yet)

from flask-socketio.

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024

I have never spent the time to add catch-all handlers in this package, and there is currently no testing beyond what I added for this fix. Before I can release this as a supported feature I need to do some more work and build tests.

from flask-socketio.

mooomooo avatar mooomooo commented on September 23, 2024

Ah I see; thanks for your diligence!

from flask-socketio.

x90slide avatar x90slide commented on September 23, 2024

Please add catch all event handling. And on that subject, Please add dynamic event registering and unregistering at runtime.

from flask-socketio.

miguelgrinberg avatar miguelgrinberg commented on September 23, 2024

Please add dynamic event registering and unregistering at runtime.

Not planning to do this. You can implement this yourself for your application using a class-based namespace (or a catch-all event handler once I add them properly to this package) if this is important to you.

from flask-socketio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.