fix: SSE sync indicator stuck on 'Connexion...' (3 fixes)
1. Move initSyncStatus() AFTER auth check — EventSource was connecting before the access_token cookie was available, causing 401 errors. 2. Reconnect SSE after login — Login form handler now calls IndexUpdateManager.connect() + showWelcome() after successful auth. 3. SSESafeGZipMiddleware — GZip buffering breaks Server-Sent Events streaming. Custom middleware subclass skips compression for /api/events endpoint (path-based bypass).
This commit is contained in:
parent
2469026c1d
commit
a5afbb1dc1
@ -556,8 +556,24 @@ async def lifespan(app: FastAPI):
|
|||||||
app = FastAPI(title="ObsiGate", version="1.4.0", lifespan=lifespan)
|
app = FastAPI(title="ObsiGate", version="1.4.0", lifespan=lifespan)
|
||||||
|
|
||||||
# GZip compression — reduces bandwidth by ~70% for text responses
|
# GZip compression — reduces bandwidth by ~70% for text responses
|
||||||
|
# Custom wrapper: skip compression for SSE streams (/api/events)
|
||||||
from fastapi.middleware.gzip import GZipMiddleware
|
from fastapi.middleware.gzip import GZipMiddleware
|
||||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
from starlette.types import Scope, Receive, Send
|
||||||
|
|
||||||
|
class SSESafeGZipMiddleware(GZipMiddleware):
|
||||||
|
"""GZip middleware that skips SSE (Server-Sent Events) streams.
|
||||||
|
|
||||||
|
GZip buffering breaks incremental streaming required by SSE.
|
||||||
|
We detect SSE endpoints by path and bypass compression entirely.
|
||||||
|
"""
|
||||||
|
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||||
|
if scope["type"] == "http" and scope.get("path") == "/api/events":
|
||||||
|
# Bypass GZip: passthrough directly to the inner app
|
||||||
|
await self.app(scope, receive, send)
|
||||||
|
else:
|
||||||
|
await super().__call__(scope, receive, send)
|
||||||
|
|
||||||
|
app.add_middleware(SSESafeGZipMiddleware, minimum_size=1000)
|
||||||
|
|
||||||
# Security headers on all responses
|
# Security headers on all responses
|
||||||
app.add_middleware(SecurityHeadersMiddleware)
|
app.add_middleware(SecurityHeadersMiddleware)
|
||||||
|
|||||||
@ -1734,6 +1734,10 @@
|
|||||||
// Load app data after successful login
|
// Load app data after successful login
|
||||||
try {
|
try {
|
||||||
await Promise.all([loadVaults(), loadTags()]);
|
await Promise.all([loadVaults(), loadTags()]);
|
||||||
|
// Start SSE sync now that auth cookie is set
|
||||||
|
IndexUpdateManager.connect();
|
||||||
|
// Show dashboard
|
||||||
|
showWelcome();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to load data after login:", err);
|
console.error("Failed to load data after login:", err);
|
||||||
}
|
}
|
||||||
@ -7818,7 +7822,6 @@
|
|||||||
initSidebarFilter();
|
initSidebarFilter();
|
||||||
initSidebarResize();
|
initSidebarResize();
|
||||||
initEditor();
|
initEditor();
|
||||||
initSyncStatus();
|
|
||||||
initLoginForm();
|
initLoginForm();
|
||||||
initRecentTab();
|
initRecentTab();
|
||||||
RightSidebarManager.init();
|
RightSidebarManager.init();
|
||||||
@ -7829,6 +7832,9 @@
|
|||||||
const authOk = await AuthManager.initAuth();
|
const authOk = await AuthManager.initAuth();
|
||||||
|
|
||||||
if (authOk) {
|
if (authOk) {
|
||||||
|
// Start SSE sync AFTER auth is established (cookie available)
|
||||||
|
initSyncStatus();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all([loadVaultSettings(), loadVaults(), loadTags()]);
|
await Promise.all([loadVaultSettings(), loadVaults(), loadTags()]);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user