mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 14:49:09 +02:00
When NEXT_PUBLIC_WS_URL is not set, the WebSocket URL defaulted to ws://localhost:8080/ws. This broke real-time features (chat streaming, live updates, notifications) for self-hosted deployments accessed over LAN — the browser tried connecting to localhost on the client machine instead of the Docker host. Now the web app derives the WebSocket URL from window.location, routing through the existing Next.js /ws rewrite. This works for localhost, LAN, and custom domain setups without any extra configuration. Also adds NEXT_PUBLIC_WS_URL as a Docker build arg for explicit override, and documents LAN access configuration in SELF_HOSTING_ADVANCED.md. Closes #896
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { CoreProvider } from "@multica/core/platform";
|
|
import { WebNavigationProvider } from "@/platform/navigation";
|
|
import {
|
|
setLoggedInCookie,
|
|
clearLoggedInCookie,
|
|
} from "@/features/auth/auth-cookie";
|
|
|
|
// Legacy token in localStorage → keep this session in token mode so users who
|
|
// logged in before the cookie-auth migration stay authed. They migrate to
|
|
// cookie mode on their next logout/login cycle (logout clears multica_token).
|
|
// Sunset: once telemetry shows <1% of sessions still carry multica_token,
|
|
// delete this branch and hard-code `cookieAuth` — the localStorage token is
|
|
// XSS-exposed and is the exact thing the cookie migration exists to remove.
|
|
function hasLegacyToken(): boolean {
|
|
if (typeof window === "undefined") return false;
|
|
try {
|
|
return Boolean(window.localStorage.getItem("multica_token"));
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Derive WebSocket URL from the page origin so self-hosted / LAN deployments
|
|
// work without explicit NEXT_PUBLIC_WS_URL. The Next.js rewrite rule
|
|
// (/ws → backend) handles proxying.
|
|
function deriveWsUrl(): string | undefined {
|
|
if (process.env.NEXT_PUBLIC_WS_URL) return process.env.NEXT_PUBLIC_WS_URL;
|
|
if (typeof window === "undefined") return undefined;
|
|
const proto = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
return `${proto}//${window.location.host}/ws`;
|
|
}
|
|
|
|
export function WebProviders({ children }: { children: React.ReactNode }) {
|
|
const cookieAuth = !hasLegacyToken();
|
|
return (
|
|
<CoreProvider
|
|
apiBaseUrl={process.env.NEXT_PUBLIC_API_URL}
|
|
wsUrl={deriveWsUrl()}
|
|
cookieAuth={cookieAuth}
|
|
onLogin={setLoggedInCookie}
|
|
onLogout={clearLoggedInCookie}
|
|
>
|
|
<WebNavigationProvider>{children}</WebNavigationProvider>
|
|
</CoreProvider>
|
|
);
|
|
}
|