miguelgrinberg / flask-sock

Modern WebSocket support for Flask.
MIT License
271 stars 24 forks source link

Using sessions #31

Closed rickwierenga closed 2 years ago

rickwierenga commented 2 years ago

First off, thanks for all of your amazing work.

I am looking to use sessions with flask-sock, and found your tutorial for socketio here. Unfortunately this does not work with this library (yet). I am willing to create a PR for this, but would appreciate a pointer on where to start.

Here's a minimal reproducible example:

# app.py
from flask import Flask, jsonify, render_template, session
from flask_session import Session
from flask_sock import Sock

app = Flask(__name__, template_folder='.')
app.config["SECRET_KEY"] = "whatever"
app.config['SESSION_TYPE'] = 'filesystem'
sess = Session()
sess.init_app(app)
sock = Sock(app)

@app.route("/")
def index():
  session["index"] = True
  return render_template("index.html")

@sock.route("/ws")
def handle_ws(ws):
  session["ws"] = True
  while True:
    message = ws.receive()
    ws.send(session)

@app.route("/session")
def get_session():
  return jsonify(session)

if __name__ == "__main__":
  app.run(port=5001)
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <script>
      function startWebsocket() {
        var ws = new WebSocket("ws://localhost:5001/ws");
        ws.onopen = function () {
          console.log("Connected to websocket");
          ws.send("Hello, world!");
        };
        ws.onmessage = function (event) {
          console.log("Received message from websocket");
          console.log(event.data);
        };
        ws.onclose = function () {
          console.log("Disconnected from websocket");
        };
      }

      window.onload = startWebsocket;
    </script>
  </body>
</html>

Thanks again!

miguelgrinberg commented 2 years ago

Are you trying to send the session dictionary as a websocket message? You can only send text or bytes, maybe that is the problem?

rickwierenga commented 2 years ago

It's automatically converted to its string representation, so that actually works fine. It is missing the index key, however, while ws is set to True. Visiting /session afterwards shows index=True, and no value for ws.

miguelgrinberg commented 2 years ago

@rickwierenga I don't understand what is the problem. Running your code, the websocket client displays the correct session data:

Connected to websocket
Received message from websocket
<FileSystemSession {'_permanent': True, 'index': True, 'ws': True}>

And the /session endpoint as well:

{"_permanent":true,"index":true}

If you were expecting the ws key to be seen by the /session endpoint, that is incorrect. Flask saves the session when a route exits. Your WebSocket route runs a loop and never exits, so the session changes you make in this route will not be saved, unless you save them yourself.

rickwierenga commented 2 years ago

Flask saves the session when a route exits.

Didn't know that, thanks for explaining.