xuminglong commited on
Commit
6207c44
·
1 Parent(s): 71faf97
Files changed (1) hide show
  1. app.py +54 -20
app.py CHANGED
@@ -184,40 +184,63 @@ def _has_active_tasks(task_list):
184
  app = FastAPI(title="CloudFileRelay|Online Files to Cloud Drive")
185
 
186
  # 会话存储
 
187
  sessions: dict = {}
188
 
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  def get_or_create_session(request: Request) -> tuple:
191
- sid = request.cookies.get("sid", "")
 
 
 
 
192
  if sid and sid in sessions:
193
  return sid, sessions[sid]
194
- sid = uuid.uuid4().hex
195
 
196
- test_tasks = []
197
- if ENABLE_TEST_DATA:
198
- # 初始化一些测试数据以展示分页效果
199
- for i in range(45):
200
- test_tasks.append({
201
- "trace_id": f"test_{20240208}_{i:03d}",
202
- "run_id": str(123456 + i),
203
- "filename": f"测试文件_{i:03d}.mp4",
204
- "url": f"https://example.com/file_{i:03d}.mp4",
205
- "status": "已转存" if i % 3 != 0 else "失败",
206
- "share_url": f"https://quark.cn/s/{"abcdefghijk"[i%11]*12}" if i % 3 != 0 else "",
207
- "created_at": f"2026-02-08 10:{i//60:02d}:{i%60:02d}",
208
- })
209
 
210
- sessions[sid] = test_tasks
 
 
211
  return sid, sessions[sid]
212
 
213
 
214
  def json_resp(data: dict, sid: str) -> JSONResponse:
 
 
 
 
215
  resp = JSONResponse(content=data)
216
- resp.set_cookie("sid", sid, max_age=86400 * 7, httponly=True, samesite="lax")
 
217
  return resp
218
 
219
 
220
  # ---- 请求模型 ----
 
221
  class SubmitRequest(BaseModel):
222
  url: str
223
  filename: str = ""
@@ -232,10 +255,11 @@ class QueryRequest(BaseModel):
232
  async def index(request: Request):
233
  sid, _ = get_or_create_session(request)
234
  resp = HTMLResponse(content=HTML_TEMPLATE)
235
- resp.set_cookie("sid", sid, max_age=86400 * 7, httponly=True, samesite="lax")
236
  return resp
237
 
238
 
 
239
  # ---- API ----
240
  @app.get("/api/extract-filename")
241
  async def api_extract_filename(url: str = Query("")):
@@ -995,12 +1019,22 @@ function renderPaginationControls(totalPages) {
995
  API Helper
996
  ============================================================ */
997
  async function api(endpoint, method, body) {
998
- const opt = { method: method || 'GET', headers: {'Content-Type':'application/json'} };
 
 
 
 
 
 
 
999
  if (body) opt.body = JSON.stringify(body);
1000
  const r = await fetch(endpoint, opt);
1001
- return await r.json();
 
 
1002
  }
1003
 
 
1004
  /* ============================================================
1005
  URL → 文件名自动提取
1006
  ============================================================ */
 
184
  app = FastAPI(title="CloudFileRelay|Online Files to Cloud Drive")
185
 
186
  # 会话存储
187
+ SESSION_FILE = "sessions_db.json"
188
  sessions: dict = {}
189
 
190
 
191
+ def load_sessions():
192
+ global sessions
193
+ if os.path.exists(SESSION_FILE):
194
+ try:
195
+ with open(SESSION_FILE, "r", encoding="utf-8") as f:
196
+ sessions = json.load(f)
197
+ except Exception:
198
+ sessions = {}
199
+
200
+
201
+ def save_sessions():
202
+ try:
203
+ with open(SESSION_FILE, "w", encoding="utf-8") as f:
204
+ json.dump(sessions, f, ensure_ascii=False, indent=2)
205
+ except Exception:
206
+ pass
207
+
208
+
209
+ load_sessions()
210
+
211
+
212
  def get_or_create_session(request: Request) -> tuple:
213
+ # 优先从 header 获取 sid,作为 fallback 方案,解决 iframe 跨域 Cookie 丢失问题
214
+ sid = request.headers.get("X-Session-ID", "")
215
+ if not sid:
216
+ sid = request.cookies.get("sid", "")
217
+
218
  if sid and sid in sessions:
219
  return sid, sessions[sid]
 
220
 
221
+ # 如果 sid 已经存在但不在 sessions 中(可能服务器重启),仍保留原 sid 以维持客户端一致性
222
+ if not sid:
223
+ sid = uuid.uuid4().hex
 
 
 
 
 
 
 
 
 
 
224
 
225
+ if sid not in sessions:
226
+ sessions[sid] = []
227
+ save_sessions()
228
  return sid, sessions[sid]
229
 
230
 
231
  def json_resp(data: dict, sid: str) -> JSONResponse:
232
+ # 每次有变更时保存会话(这里简单处理,实际高并发下建议异步或定时保存)
233
+ save_sessions()
234
+ # 在响应体中携带 sid,方便前端存入 localStorage
235
+ data["sid"] = sid
236
  resp = JSONResponse(content=data)
237
+ # 使用 samesite="none" secure=True 以支持在 Hugging Face Spaces 等 iframe 环境中正常传递 Cookie
238
+ resp.set_cookie("sid", sid, max_age=86400 * 7, httponly=True, samesite="none", secure=True)
239
  return resp
240
 
241
 
242
  # ---- 请求模型 ----
243
+
244
  class SubmitRequest(BaseModel):
245
  url: str
246
  filename: str = ""
 
255
  async def index(request: Request):
256
  sid, _ = get_or_create_session(request)
257
  resp = HTMLResponse(content=HTML_TEMPLATE)
258
+ resp.set_cookie("sid", sid, max_age=86400 * 7, httponly=True, samesite="none", secure=True)
259
  return resp
260
 
261
 
262
+
263
  # ---- API ----
264
  @app.get("/api/extract-filename")
265
  async def api_extract_filename(url: str = Query("")):
 
1019
  API Helper
1020
  ============================================================ */
1021
  async function api(endpoint, method, body) {
1022
+ const sid = localStorage.getItem('sid') || '';
1023
+ const opt = {
1024
+ method: method || 'GET',
1025
+ headers: {
1026
+ 'Content-Type':'application/json',
1027
+ 'X-Session-ID': sid
1028
+ }
1029
+ };
1030
  if (body) opt.body = JSON.stringify(body);
1031
  const r = await fetch(endpoint, opt);
1032
+ const d = await r.json();
1033
+ if (d.sid) localStorage.setItem('sid', d.sid);
1034
+ return d;
1035
  }
1036
 
1037
+
1038
  /* ============================================================
1039
  URL → 文件名自动提取
1040
  ============================================================ */