From fb140c0f431cc49e62ddf03373a87bd5acaf5af4 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Fri, 7 Nov 2025 13:18:04 +1100 Subject: [PATCH] don't need to pull port out --- .../settings/tunnel/TunnelSection.tsx | 28 ++++++++----------- ui/desktop/src/main.ts | 12 ++++---- ui/desktop/src/preload.ts | 12 ++++---- ui/desktop/src/utils/tunnel.ts | 17 +++++------ 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/ui/desktop/src/components/settings/tunnel/TunnelSection.tsx b/ui/desktop/src/components/settings/tunnel/TunnelSection.tsx index bbfb7263d0..558005ca7f 100644 --- a/ui/desktop/src/components/settings/tunnel/TunnelSection.tsx +++ b/ui/desktop/src/components/settings/tunnel/TunnelSection.tsx @@ -22,10 +22,9 @@ export default function TunnelSection() { useEffect(() => { const loadTunnelStatus = async () => { try { - const portStr = await window.electron.getGoosedHostPort(); - if (!portStr) throw new Error('No port available'); - const port = parseInt(portStr.replace('http://127.0.0.1:', '')); - const status = await window.electron.getTunnelStatus(port); + const baseUrl = await window.electron.getGoosedHostPort(); + if (!baseUrl) throw new Error('goose server not available'); + const status = await window.electron.getTunnelStatus(baseUrl); setTunnelStatus(status); } catch (err) { setError(errorMessage(err, 'Failed to load tunnel status')); @@ -41,10 +40,9 @@ export default function TunnelSection() { setTunnelStatus((prev) => ({ ...prev, state: 'starting', info: null })); try { - const portStr = await window.electron.getGoosedHostPort(); - if (!portStr) throw new Error('No port available'); - const port = parseInt(portStr.replace('http://127.0.0.1:', '')); - const tunnelInfo = await window.electron.startTunnel(port); + const baseUrl = await window.electron.getGoosedHostPort(); + if (!baseUrl) throw new Error('goose server not available'); + const tunnelInfo = await window.electron.startTunnel(baseUrl); setTunnelStatus((prev) => ({ ...prev, state: 'running', info: tunnelInfo })); setShowQRModal(true); } catch (err) { @@ -55,19 +53,17 @@ export default function TunnelSection() { const handleStopTunnel = async () => { try { - const portStr = await window.electron.getGoosedHostPort(); - if (!portStr) throw new Error('No port available'); - const port = parseInt(portStr.replace('http://127.0.0.1:', '')); - await window.electron.stopTunnel(port); + const baseUrl = await window.electron.getGoosedHostPort(); + if (!baseUrl) throw new Error('No port available'); + await window.electron.stopTunnel(baseUrl); setTunnelStatus((prev) => ({ ...prev, state: 'idle', info: null })); setShowQRModal(false); } catch (err) { setError(errorMessage(err, 'Failed to stop tunnel')); try { - const portStr = await window.electron.getGoosedHostPort(); - if (!portStr) throw new Error('No port available'); - const port = parseInt(portStr.replace('http://127.0.0.1:', '')); - const status = await window.electron.getTunnelStatus(port); + const baseUrl = await window.electron.getGoosedHostPort(); + if (!baseUrl) throw new Error('No port available'); + const status = await window.electron.getTunnelStatus(baseUrl); setTunnelStatus(status); } catch (statusErr) { console.error('Failed to fetch tunnel status after error:', statusErr); diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 25edd3a3fd..ef6428ced8 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -1227,10 +1227,10 @@ ipcMain.handle('get-wakelock-state', () => { } }); -ipcMain.handle('start-tunnel', async (_event, port: number) => { +ipcMain.handle('start-tunnel', async (_event, baseUrl: string) => { try { const { startTunnel } = await import('./utils/tunnel'); - const tunnelInfo = await startTunnel(port, SERVER_SECRET); + const tunnelInfo = await startTunnel(baseUrl, SERVER_SECRET); return tunnelInfo; } catch (error) { console.error('Error starting tunnel:', error); @@ -1238,20 +1238,20 @@ ipcMain.handle('start-tunnel', async (_event, port: number) => { } }); -ipcMain.handle('stop-tunnel', async (_event, port: number) => { +ipcMain.handle('stop-tunnel', async (_event, baseUrl: string) => { try { const { stopTunnel } = await import('./utils/tunnel'); - await stopTunnel(port, SERVER_SECRET); + await stopTunnel(baseUrl, SERVER_SECRET); } catch (error) { console.error('Error stopping tunnel:', error); throw error; } }); -ipcMain.handle('get-tunnel-status', async (_event, port: number) => { +ipcMain.handle('get-tunnel-status', async (_event, baseUrl: string) => { try { const { syncTunnelStatus } = await import('./utils/tunnel'); - return await syncTunnelStatus(port, SERVER_SECRET); + return await syncTunnelStatus(baseUrl, SERVER_SECRET); } catch (error) { console.error('Error getting tunnel status:', error); return { state: 'error', info: null, auto_start: false }; diff --git a/ui/desktop/src/preload.ts b/ui/desktop/src/preload.ts index e3fcd59df2..58d0aecca7 100644 --- a/ui/desktop/src/preload.ts +++ b/ui/desktop/src/preload.ts @@ -121,9 +121,9 @@ type ElectronAPI = { hasAcceptedRecipeBefore: (recipe: Recipe) => Promise; recordRecipeHash: (recipe: Recipe) => Promise; openDirectoryInExplorer: (directoryPath: string) => Promise; - startTunnel: (port: number) => Promise; - stopTunnel: (port: number) => Promise; - getTunnelStatus: (port: number) => Promise; + startTunnel: (baseUrl: string) => Promise; + stopTunnel: (baseUrl: string) => Promise; + getTunnelStatus: (baseUrl: string) => Promise; }; type AppConfigAPI = { @@ -260,9 +260,9 @@ const electronAPI: ElectronAPI = { recordRecipeHash: (recipe: Recipe) => ipcRenderer.invoke('record-recipe-hash', recipe), openDirectoryInExplorer: (directoryPath: string) => ipcRenderer.invoke('open-directory-in-explorer', directoryPath), - startTunnel: (port: number) => ipcRenderer.invoke('start-tunnel', port), - stopTunnel: (port: number) => ipcRenderer.invoke('stop-tunnel', port), - getTunnelStatus: (port: number) => ipcRenderer.invoke('get-tunnel-status', port), + startTunnel: (baseUrl: string) => ipcRenderer.invoke('start-tunnel', baseUrl), + stopTunnel: (baseUrl: string) => ipcRenderer.invoke('stop-tunnel', baseUrl), + getTunnelStatus: (baseUrl: string) => ipcRenderer.invoke('get-tunnel-status', baseUrl), }; const appConfigAPI: AppConfigAPI = { diff --git a/ui/desktop/src/utils/tunnel.ts b/ui/desktop/src/utils/tunnel.ts index 7542045897..5419acae16 100644 --- a/ui/desktop/src/utils/tunnel.ts +++ b/ui/desktop/src/utils/tunnel.ts @@ -23,16 +23,17 @@ export interface TunnelStatus { /** * Start the tunnel via Rust API and remember it */ -export async function startTunnel(goosedPort: number, serverSecret: string): Promise { - log.info(`Starting tunnel via Rust API on port ${goosedPort}`); +export async function startTunnel(baseUrl: string, serverSecret: string): Promise { + log.info(`Starting tunnel via Rust API at ${baseUrl}`); - const response = await fetch(`http://127.0.0.1:${goosedPort}/api/tunnel/start`, { + const port = parseInt(baseUrl.replace('http://127.0.0.1:', '')); + const response = await fetch(`${baseUrl}/api/tunnel/start`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Secret-Key': serverSecret, }, - body: JSON.stringify({ port: goosedPort }), + body: JSON.stringify({ port }), }); if (!response.ok) { @@ -53,11 +54,11 @@ export async function startTunnel(goosedPort: number, serverSecret: string): Pro /** * Stop the tunnel via Rust API, and remember it */ -export async function stopTunnel(port: number, secret: string): Promise { +export async function stopTunnel(baseUrl: string, secret: string): Promise { log.info('Stopping tunnel via Rust API'); try { - const response = await fetch(`http://127.0.0.1:${port}/api/tunnel/stop`, { + const response = await fetch(`${baseUrl}/api/tunnel/stop`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -79,8 +80,8 @@ export async function stopTunnel(port: number, secret: string): Promise { * Get tunnel status from Rust API * Note: Rust backend is the source of truth */ -export async function syncTunnelStatus(port: number, secret: string): Promise { - const response = await fetch(`http://127.0.0.1:${port}/api/tunnel/status`, { +export async function syncTunnelStatus(baseUrl: string, secret: string): Promise { + const response = await fetch(`${baseUrl}/api/tunnel/status`, { headers: { 'X-Secret-Key': secret, },