So I am trying to delete the user's session if the page has been closed long enough and the user has not reopened the page again. So to test it you just open the webpage and then close it with the server still up.
Here is some example code demonstrating my problem:
from flask import Flask, session, render_template, url_for, redirect
from flask_socketio import SocketIO, join_room
from flask_session import Session
from threading import Thread
from time import sleep
app = Flask(__name__)
app.config['SECRET_KEY'] = 'temporary2'
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
socketio = SocketIO(app, manage_session=False)
deletelist = {}
@app.route('/')
def index():
return render_template('wait.html')
@app.route('/dir')
def foo():
if "name" in session:
name = session['name']
return f"Hello, {name}!"
else:
return redirect(url_for("index"))
@socketio.on('log')
def connection(request):
if "name" not in session:
join_room('waiting')
session['name'] = 'craig'
session.modified = True
socketio.emit('redirect', url_for('foo'), room='waiting')
else:
deletelist[session['name']]= False #this line stops the user session being deleted if they relog soon enough e.g. reloading the page
print('relogin')
def clear_session():
with app.app_context():
session.clear()
print('Session cleared')
@socketio.on('disconnect')
def disconnect():
def sessiondelete(sess,t):
if deletelist[sess]==False:
print('cancelled')
del deletelist[sess]
elif t == 5:#the time would be more than 5 seconds this is just to test
print('cleared')
clear_session()
del deletelist[sess]
elif deletelist[sess]==True:
print('poll')
sleep(1)
sessiondelete(sess,t+1)
deletelist[session['name']]= True #error arises if you just store session, as it is not hashable
print('init')
worker = Thread(target=sessiondelete, args=(session['name'],0))# I create seperate thread so the rest of the server can still function for other users
worker.start()
if __name__ == '__main__':
socketio.run(app, port=5200, debug=True)
The functioniality of the disconnect and relog works but it will raise an error when it reaches the session clear in the delete session function. I have tried passing the session from the disconnect function and app.app_context()
to no avail. The error has something to do that the function clearing the function does not have the flask and socket decorators, so it cannot process the request?
The console logs if you are wondering: init poll poll poll poll poll going to clear File "/Volumes/src/testing/test.py", line 46, in sessiondelete clear_session(session) File "/Volumes/src/testing/test.py", line 35, in clear_session session.clear() RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.
And the html if you need
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
Waiting...
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script>
const socket = io();
socket.emit("log", { data: "connection" });
socket.on('redirect', (dest) => {
window.location = dest;
});
</script>
</body>
</html>
The session is only accessible in the context of the event handlers. When you start a background thread the association with a client is lost, the thread is just a thread, it does not know who the client is, so it has no way to access the session from that or any other client.
I'm not sure I understand why you use such a complicated solution. If you run your wait loop directly in your handler, I think everything should work. And this should not block other clients from sending or receiving events.