Reputation: 1841
I need to be able to modify a session variable in a Flask route that returns a stream, but it isn't working. I'm sure I'm missing something obvious but I cannot see what it is. I've simplified and reduced the code as far as possible:
from flask import Flask, Response, render_template, session, stream_with_context
from flask_session import Session
from cachelib.file import FileSystemCache
app = Flask(__name__)
SESSION_TYPE = 'cachelib'
SESSION_SERIALIZATION_FORMAT = 'json'
SESSION_CACHELIB = FileSystemCache(threshold=500, cache_dir="/sessions")
app.config.from_object(__name__)
Session(app)
@app.route('/')
def home():
session['history'] = []
return render_template('index.html')
@app.route('/route1')
def route1():
session['history'].append('route1')
session.modified = True
return {"history": session['history']}
@app.route('/route2')
def route2():
def generate():
full_response = ''
for piece in text_generator():
full_response += piece
yield f"data: {piece}\n\n"
session['history'].append(full_response)
session.modified = True
return Response(stream_with_context(generate()), mimetype='text/event-stream')
@app.route('/reset')
def reset():
session['history'] = []
session.modified = True
return 'Reset complete.'
# In reality this returns different text each time, from AI
def text_generator():
yield 'route2'
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask Session Test</title>
<script>
async function fetchRoute(route) {
const response = await fetch(route);
if (response.ok) {
const data = await response.json();
document.getElementById('response').textContent = JSON.stringify(data, null, 2) + '\n';
}
}
function setupEventSource() {
const eventSource = new EventSource('/route2');
eventSource.onmessage = function(event) {
document.getElementById('response').textContent += event.data + '\n';
};
eventSource.onerror = function(event) {
console.error("EventSource failed:", event);
eventSource.close();
};
eventSource.onopen = function() {
console.log("Connection to /route2 opened.");
document.getElementById('response').textContent += 'Streaming data from /route2...\n';
};
}
async function resetSession() {
const response = await fetch('/reset');
const data = await response.text();
document.getElementById('response').textContent = data;
}
</script>
</head>
<body>
<h1>Flask Session Test</h1>
<button onclick="fetchRoute('/route1')">Trigger Route 1</button>
<button onclick="setupEventSource()">Trigger Route 2</button>
<button onclick="resetSession()">Reset Session</button>
<pre id="response"></pre>
</body>
</html>
Click Route1, then Route2, then Route1 again: I would expect (and require) the history to include "Route2", but it does not. This is the session extension I'm using: https://flask-session.readthedocs.io/en/latest/usage.html Thanks in advance for any advice.
Upvotes: 0
Views: 33