Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility to ws.send from another Flask route #19

Closed
danohn opened this issue Jan 21, 2022 · 7 comments
Closed

Possibility to ws.send from another Flask route #19

danohn opened this issue Jan 21, 2022 · 7 comments
Labels
question Further information is requested

Comments

@danohn
Copy link

danohn commented Jan 21, 2022

Hi Miguel, I have a Flask route which accepts a POST request with a parameters. Given one of the parameters is 'hello', is it possible to ws.send this 'hello' string to one of the connected ws clients? My app is purely server to client messages. Thanks!

@miguelgrinberg
Copy link
Owner

@danohn Yes, I don't see why not. The ws object wraps a network socket, anything you send on it will go to the other end. Your application will have to have a way to find the correct ws object for the client you want to address though.

@miguelgrinberg miguelgrinberg added the question Further information is requested label Jan 21, 2022
@danohn
Copy link
Author

danohn commented Jan 21, 2022

Thanks @miguelgrinberg I'll try that out and share the results here

@danohn
Copy link
Author

danohn commented Jan 22, 2022

Hi @miguelgrinberg , I'm clearly not doing something right or not understanding the code, apologies! Here is my Flask app:

from flask import Flask, render_template, request
from flask_sock import Sock

app = Flask(__name__)
sock = Sock(app)

@app.route('/publish', methods=['POST'])
def publish_route():
    message = request.form['message']
    sock.send(message)
    return f'Message sent: {message}'


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


@sock.route('/echo')
def echo(sock):
    while True:
        data = sock.receive()
        sock.send(data)


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

What I am trying to achieve is when someone sends a POST request to /publish, I extract the message from the POST form and then I want to send that message to the JS client which has already connected to the server on the /echo route.

@danohn
Copy link
Author

danohn commented Jan 22, 2022

By the way, with the above code, my index.html is identical to your example.

@miguelgrinberg
Copy link
Owner

miguelgrinberg commented Jan 22, 2022

This is partly my fault, because the example code in which you based this was confusing, in that it used the sock variable name for two completely different purposes. I apologize for that, I have now removed this ambiguity from the code.

The WebSocket route now looks like this:

@sock.route('/echo')
def echo(ws):
    while True:
        data = ws.receive()
        ws.send(data)

So hopefully it is now more clear what you need to do. The ws variable that you need to use to send something to your client is a local variable of the WebSocket route, and there are actually multiple ones, one for each active client. Your application needs to use some sort of data structure (maybe a global dictionary or list) to keep track of these variables somewhere your route can find them.

I mentioned this in my previous reply:

Your application will have to have a way to find the correct ws object for the client you want to address though.

@danohn
Copy link
Author

danohn commented Jan 25, 2022

Thanks @miguelgrinberg , it looks like flask-socketio might be a better project for my use case. Appreciate the help :)

@danohn danohn closed this as completed Jan 25, 2022
@danohn
Copy link
Author

danohn commented Feb 22, 2022

Hi @miguelgrinberg ,

I just wanted to provide a quick update. I ended up implementing this with your Flask-SocketIO library. Here is the code I am using:

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

app = Flask(__name__)

socketio = SocketIO(app)

@app.route("/publish", methods=["POST"])
def publish_route():
    msg = request.form["msg"]
    socketio.emit('my_topic', msg)
    return f"Message sent: {msg}"

@app.route("/", methods=['GET'])
def index_route():
    return render_template("index.html")

if __name__ == "__main__":
    socketio.run(app)

Just out of interest, would the same have been possible with Flask-Sock?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants