From e12894099f04e2e2ae019cc4cd6ebcd2e9ecf67e Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sun, 14 Jun 2026 12:32:47 +0200 Subject: [PATCH] feat(uniweb): point the bus at the same-origin proxy, drop the IP fallback The SPA is now served behind a same-origin reverse proxy (Caddy) that fronts both bus planes, so the data layer reaches them through the page's own origin instead of a hardcoded cluster node IP. This removes CORS entirely and hides the cluster IPs behind the proxy. - BUS_HTTP falls back to the relative path /api (the signed HTTPS control plane), resolved against the page origin by ControlPlane's fetch. - BUS_WS falls back to a wss URL derived from window.location (same host, scheme mirroring https/http, path /nats), since a browser WebSocket needs an absolute ws(s) URL. - The raw self-signed-IP fallback (https://51.91.100.142:8470, wss://...:8480) is gone. The VITE_BUS_HTTP / VITE_BUS_WS build-time overrides remain for a dev setup that points straight at a cluster node. Co-Authored-By: Claude Opus 4.8 (1M context) --- web/src/busService.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/web/src/busService.ts b/web/src/busService.ts index 00d8b67..eb87d47 100644 --- a/web/src/busService.ts +++ b/web/src/busService.ts @@ -24,11 +24,26 @@ import { import type { WalletIdentity } from "./wallet/derive"; import type { MeInfo, Message, Room, User } from "./types"; -// Bus endpoints. A browser cannot open a raw TCP NATS socket, so the data plane is -// reached over WebSocket; the control plane is the signed HTTPS API. Both default to -// a cluster node and can be overridden at build time (VITE_BUS_HTTP / VITE_BUS_WS). -const BUS_HTTP = import.meta.env.VITE_BUS_HTTP ?? "https://51.91.100.142:8470"; -const BUS_WS = import.meta.env.VITE_BUS_WS ?? "wss://51.91.100.142:8480"; +// Bus endpoints. The SPA is served same-origin behind a reverse proxy (Caddy): +// both planes are reached through this page's OWN origin, so there is no CORS and +// the cluster node IPs stay hidden behind the proxy. The control plane is the +// signed HTTPS API under the relative path /api; the data plane is NATS over +// WebSocket under /nats (a browser cannot open a raw TCP NATS socket). Both can +// still be overridden at build time (VITE_BUS_HTTP / VITE_BUS_WS) for a dev setup +// that points straight at a cluster node. +const BUS_HTTP = import.meta.env.VITE_BUS_HTTP ?? "/api"; +const BUS_WS = import.meta.env.VITE_BUS_WS ?? defaultBusWS(); + +// defaultBusWS derives the data-plane WebSocket URL from the page origin: the same +// host and port as the SPA, the wss/ws scheme mirroring https/http, path /nats. A +// browser WebSocket needs an absolute ws(s) URL, so this is computed from location +// rather than left relative. Returns "" where window is absent (SSR/tests), where +// the build-time override is expected instead. +function defaultBusWS(): string { + if (typeof window === "undefined") return ""; + const proto = window.location.protocol === "https:" ? "wss:" : "ws:"; + return `${proto}//${window.location.host}/nats`; +} export class SessionError extends Error {}