电子和烧瓶:服务器端会话变量反复初始化

问题描述 投票:0回答:1

Short版本:我正在尝试用烧瓶作为后端制作电子应用程序。我要做的部分内容涉及获取会话变量或初始化该会话变量。这是行不通的,因为即使会话变量初始化,也无法识别会话变量,从而导致每次调用路由时都会创建新变量。我怀疑这是我的CORS配置或缺乏的问题,但是我不知道怎么了或如何解决。因此,这篇文章

长版本:我的应用程序采用表单的内容并将其传递给后端,然后将其添加为节点,然后将其附加到链接列表中,然后稍后可以访问。我希望节点的一个字段,细节是唯一的。而且,为此,我想做到这一点,以便用户不能提交“详细信息”已经存在的表格。我试图通过以下JS代码来实现这一目标:

/* INPUT VALIDATION */ async function checkUniqueDetail(detail_to_check){ try{ const response=await fetch(`${SERVER_URL}/check_detail/${detail_to_check}`,{ method: "GET", headers: { Accept: "application/json", "Content-Type": "application/json", }, }); const data=await response.json(); const existing_details=data.detail_list; console.log("Existing details:", existing_details); console.log("Checking detail:", detail_to_check); const result=data.result; console.log("Result is:",result); if(result=="True"){ return false; }else{ console.log("The detail is unique"); return true; } }catch(e){ console.error(e); return false; } } /* FORM SUBMISSION */ function confirmFormSubmit(formData){ if(confirm("Are you sure you want to submit?")){ const qd=formData.get("detail"); console.log("q_detail is:",qd); /* Form validation */ checkUniqueDetail(qd).then(result=>{ isUniqueDetail=result; console.log(qd,"unique?:",isUniqueDetail); /* If validated, send info */ if(isUniqueDetail==true){ sendForm(); sendDetail(qd); message.innerText="Question added!" }else{ message.innerText="A question with this detail already exists. Please try again" } }); } } form.addEventListener("submit", async (event)=>{ event.preventDefault(); const fData = new FormData(form); confirmFormSubmit(fData); });
this呼叫看起来像这样的烧瓶应用程序的路线:

# ROUTES from flask import Flask, request, session from flask_session import Session from flask_cors import CORS import redis, json #for forcibly clearing session files import atexit app = Flask(__name__) # Configurations app.config["SECRET_KEY"]="change_later" app.config["SESSION_TYPE"] = "redis" app.config["SESSION_PERMANENT"] = False r = redis.from_url('redis://127.0.0.1:6379') app.config['SESSION_REDIS'] = r def test_redis_connection(redis_session): """Check that Redis is connected to""" try: redis_session.ping() # Check if Redis is alive print("Redis connection successful!") except redis.exceptions.ConnectionError as e: print(f"Redis connection error: {e}") exit() # Or handle the error appropriately test_redis_connection(r) app.config["CORS_HEADERS"] = "Content-Type" # Initialize Plugins sess=Session() sess.init_app(app) CORS(app,resources={r"/*": {"origins": "http://localhost*"}},) #check that the server's running and connected @app.route("/", methods=["GET","POST"]) def check(): return {"result":"Server active!"} ### ERROR!!!: This only works as a Flask app # It seems like every time this is run, # it makes a new session variable, rather than getting the old one @app.route("/add_detail/<detail>",methods=["GET","POST"]) def add_detail_to_list(detail): """Add a q_detail to a list of q_details""" # Initialize the list if it doesn't exist if 'lst' not in session: print("Session variable not found. Initializing...") session['lst'] = json.dumps([]) session.modified = True # Append to the list lst:list[str]=json.loads(session['lst']) print("Before appending:",lst) lst.append(detail) print("After appending:",lst) session['lst'] = json.dumps(lst) session.modified = True return {"response":f"{lst}"} @app.route("/get_all_details",methods=["GET"]) def get_all_details(): details:list[str]=session.get("lst",[]) return {"result":details} @app.route("/check_detail/<detail>") def check_detail(detail): details:list[str]=session.get("lst",[]) if detail in details: return {"result":"True","detail_list":details} else: return {"result":"False","detail_list":details} ## NOTE: Make sure this works in production ### ERROR!!! Doesn't work with Electron app # Maybe due to how the Flask app is killed? def clear_redis_sessions(redis_session): """Clears all session data from Redis.""" try: for key in redis_session.keys("session:*"): # Important: Use a pattern to only delete session keys redis_session.delete(key) print("Redis sessions cleared.") except Exception as e: print(f"Error clearing Redis sessions: {e}") atexit.register(clear_redis_sessions,redis_session=r) # Register the cleanup function # print(app.url_map) if __name__ == "__main__": app.run(debug=True)

IT在评论中说了这一点,但是错误发生在“/add_detail/”路由中,特别是在初始if语句中。它每次都会触发,创建一个新的会话[“ LST”]变量,而不是获取旧会话。这意味着前端获得的列表始终是空的,因此细节总是标记为唯一的,并且始终允许发送表单。
这是电子应用程序的屏幕截图,显示了这种情况:

Screenshot of Electron app showing the error 以及我的redis-cli的屏幕截图显示了创建的两个会话键:

screenshot of my redis-cli showing the two session keys that were created 我怀疑发生这种情况的原因是由于跨站点请求的性质。这是因为如果我独立运行烧瓶应用程序,则不会发生此问题:

Image of Flask app working independently 但是如果我使用卷发: Image of Redis-Cli showing session variable working correctly enter image description here 我启用了CORS,但我怀疑我没有正确配置它。但是,也许这也与我如何连接到烧瓶应用有关。这是我的主要。JS,以防万一:enter image description here const { app, BrowserWindow } = require('electron'); const { exec } = require("child_process"); /** * Connects to the Flask app */ const connectToFlask=function(){ let python; //test version python = require('child_process').spawn('py', ['./py/test_routes.py']); //executable version //python = require('child_process').execFile("routes.exe"); python.stdout.on('data', function (data) { console.log("FLASK RUNNING! data:", data.toString('utf8')); }); python.stderr.on('data', (data) => { // when error console.error(`stderr: ${data}`); console.log(`stderr: ${data}`); }); python.on("close", (code)=>{ console.log(`child process exited with code ${code}`); }); } /** * Create a new BrowserWindow that's connected to Flask with index.html as its UI */ const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }); connectToFlask(); win.loadFile('index.html'); } /** * When all the windows close, quit the app */ app.on('window-all-closed', () => { if (process.platform !== 'darwin'){ /* Kill the Flask app on close too */ exec("taskkill /f /t /im python.exe", (err, stdout, stderr) => { if (err) { console.error(err); return; } console.log(`stdout: ${stdout}`); console.log(`stderr: ${stderr}`); console.log('Flask process terminated'); }); app.quit(); } }); /** * Wait for the app to be ready, then create a new window */ app.whenReady().then(() => { createWindow(); });

没有人知道我在做什么错以及如何解决?

提前感谢您
	

即使您使用redis保存会话,cookie用于存储会话ID。 因此,有必要允许服务器端上有cookie的请求,并与cookie一起从客户端发送它们。

要随请求发送cookie,请添加

credentials: 'include'

node.js flask electron flask-cors
1个回答
0
投票

因此,也可以在服务器端接收数据,将属性添加到烧瓶cors的初始化中。
fetch(url, { credentials: 'include' }) .then(resp => resp.json()) .then(data => data.result);

这里是基于您的代码而没有Redis的整个简化示例。

supports_credentials=True
CORS(app, supports_credentials=True)


最新问题
© www.soinside.com 2019 - 2025. All rights reserved.