Spaces:
Sleeping
Sleeping
Commit
·
6207c44
1
Parent(s):
71faf97
fix bug
Browse files
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
if sid and sid in sessions:
|
| 193 |
return sid, sessions[sid]
|
| 194 |
-
sid = uuid.uuid4().hex
|
| 195 |
|
| 196 |
-
|
| 197 |
-
if
|
| 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 |
-
|
|
|
|
|
|
|
| 211 |
return sid, sessions[sid]
|
| 212 |
|
| 213 |
|
| 214 |
def json_resp(data: dict, sid: str) -> JSONResponse:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
resp = JSONResponse(content=data)
|
| 216 |
-
|
|
|
|
| 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="
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 999 |
if (body) opt.body = JSON.stringify(body);
|
| 1000 |
const r = await fetch(endpoint, opt);
|
| 1001 |
-
|
|
|
|
|
|
|
| 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 |
============================================================ */
|