diff --git a/src/App.tsx b/src/App.tsx index 70e4717..964d63c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,17 +23,10 @@ import OidcCallbackPage from '@/pages/OidcCallbackPage' import OidcSettingsPage from '@/pages/OidcSettingsPage' import axios from 'axios' -// Backend URL is baked in at build time via VITE_HF_BACKEND_BASE_URL (the -// docker-compose hf-frontend service passes it as a build ARG). Falling -// back to a same-origin call only makes sense in dev with the Vite proxy. -// localStorage override is kept as an escape hatch for one-off pointing -// (e.g. dev pointing the prod build at a local backend). -const getApiBase = (): string => { - const ls = localStorage.getItem('HF_BACKEND_BASE_URL') - if (ls) return ls - const baked = import.meta.env.VITE_HF_BACKEND_BASE_URL - return baked || '' -} +// Backend URL is baked in at build time via VITE_HF_BACKEND_BASE_URL +// (docker build --build-arg). Empty string → same-origin call (only +// works in dev with the Vite proxy). +const API_BASE = import.meta.env.VITE_HF_BACKEND_BASE_URL || '' type AppState = 'checking' | 'no-admin' | 'ready' @@ -48,7 +41,7 @@ export default function App() { const checkInitialized = async () => { try { - const res = await axios.get(`${getApiBase()}/config/status`, { timeout: 5000 }) + const res = await axios.get(`${API_BASE}/config/status`, { timeout: 5000 }) const cfg = res.data || {} if (cfg.initialized === true) { setAppState('ready') @@ -57,7 +50,7 @@ export default function App() { setAppState('no-admin') } catch (err) { const msg = err instanceof Error ? err.message : String(err) - setErrorMessage(`Backend unreachable at ${getApiBase() || ''} — ${msg}`) + setErrorMessage(`Backend unreachable at ${API_BASE || ''} — ${msg}`) setAppState('no-admin') } } diff --git a/src/hooks/useAuthConfig.ts b/src/hooks/useAuthConfig.ts index af0f0d2..da23940 100644 --- a/src/hooks/useAuthConfig.ts +++ b/src/hooks/useAuthConfig.ts @@ -45,14 +45,14 @@ async function load(): Promise { } /** Absolute backend URL for full-page OIDC redirects. */ +const BACKEND_BASE = import.meta.env.VITE_HF_BACKEND_BASE_URL || '' + export function oidcLoginHref(cfg: AuthConfig): string { - const base = localStorage.getItem('HF_BACKEND_BASE_URL') ?? '' - return `${base}${cfg.oidcLoginUrl}` + return `${BACKEND_BASE}${cfg.oidcLoginUrl}` } export function oidcLinkHref(): string { - const base = localStorage.getItem('HF_BACKEND_BASE_URL') ?? '' - return `${base}/auth/oidc/link` + return `${BACKEND_BASE}/auth/oidc/link` } export function useAuthConfig() { diff --git a/src/services/api.ts b/src/services/api.ts index 477bd30..3e4a57f 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -1,15 +1,15 @@ import axios from 'axios' -const getApiBase = (): string | undefined => { - return localStorage.getItem('HF_BACKEND_BASE_URL') ?? undefined -} +// Backend URL is the build-time VITE_HF_BACKEND_BASE_URL baked into the +// bundle by docker build --build-arg. Empty → axios uses same-origin +// (only works in dev with the Vite proxy). +const API_BASE = import.meta.env.VITE_HF_BACKEND_BASE_URL || undefined const api = axios.create({ - baseURL: getApiBase(), + baseURL: API_BASE, }) api.interceptors.request.use((config) => { - config.baseURL = getApiBase() const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` diff --git a/src/test/setup.ts b/src/test/setup.ts index ce144cc..0ad9280 100644 --- a/src/test/setup.ts +++ b/src/test/setup.ts @@ -1,11 +1,17 @@ import '@testing-library/jest-dom' import { vi } from 'vitest' +// VITE_HF_BACKEND_BASE_URL is the build-time backend URL; in tests we +// stub it via import.meta.env (api.ts + useAuthConfig + App read it). +;(import.meta as any).env = { + ...(import.meta as any).env, + VITE_HF_BACKEND_BASE_URL: 'http://localhost:8000', +} + // Mock localStorage const localStorageMock = { getItem: vi.fn((key: string) => { if (key === 'token') return 'mock-token' - if (key === 'HF_BACKEND_BASE_URL') return 'http://localhost:8000' return null }), setItem: vi.fn(),