diff --git a/desktop/src/api/client.ts b/desktop/src/api/client.ts index efa1e090..d7d61f3d 100644 --- a/desktop/src/api/client.ts +++ b/desktop/src/api/client.ts @@ -44,6 +44,10 @@ export function getDefaultBaseUrl() { return DEFAULT_BASE_URL } +export function hasExplicitDefaultBaseUrl() { + return Boolean(ENV_BASE_URL) +} + export class ApiError extends Error { constructor( public status: number, diff --git a/desktop/src/lib/desktopRuntime.test.ts b/desktop/src/lib/desktopRuntime.test.ts index 2374e263..d97f09e6 100644 --- a/desktop/src/lib/desktopRuntime.test.ts +++ b/desktop/src/lib/desktopRuntime.test.ts @@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' const clientMocks = vi.hoisted(() => ({ defaultBaseUrl: 'http://127.0.0.1:3456', + explicitDefaultBaseUrl: false, setBaseUrl: vi.fn(), setAuthToken: vi.fn(), postVerify: vi.fn(), @@ -12,6 +13,7 @@ vi.mock('../api/client', () => ({ post: clientMocks.postVerify, }, getDefaultBaseUrl: () => clientMocks.defaultBaseUrl, + hasExplicitDefaultBaseUrl: () => clientMocks.explicitDefaultBaseUrl, setAuthToken: clientMocks.setAuthToken, setBaseUrl: clientMocks.setBaseUrl, })) @@ -31,6 +33,8 @@ describe('desktopRuntime browser H5 bootstrap', () => { beforeEach(() => { vi.clearAllMocks() + clientMocks.defaultBaseUrl = 'http://127.0.0.1:3456' + clientMocks.explicitDefaultBaseUrl = false vi.useRealTimers() window.localStorage.clear() window.history.pushState({}, '', '/') @@ -111,6 +115,26 @@ describe('desktopRuntime browser H5 bootstrap', () => { }) }) + it('prefers an explicit Vite desktop server URL over the dev server origin', async () => { + clientMocks.defaultBaseUrl = 'http://127.0.0.1:55189' + clientMocks.explicitDefaultBaseUrl = true + window.history.pushState({}, '', '/') + globalThis.fetch = vi.fn().mockResolvedValue( + new Response(null, { status: 200 }), + ) as typeof fetch + + await expect(initializeDesktopServerUrl()).resolves.toBe('http://127.0.0.1:55189') + + expect(clientMocks.setBaseUrl).toHaveBeenLastCalledWith('http://127.0.0.1:55189') + expect(clientMocks.setAuthToken).toHaveBeenLastCalledWith(null) + expect(globalThis.fetch).toHaveBeenCalledWith('http://127.0.0.1:55189/health', { + cache: 'no-store', + }) + expect(globalThis.fetch).toHaveBeenCalledWith('http://127.0.0.1:55189/api/status', { + cache: 'no-store', + }) + }) + it('normalizes unreachable remote browser startup into a recoverable H5 error', async () => { vi.useFakeTimers() globalThis.fetch = vi.fn().mockRejectedValue(new TypeError('Failed to fetch')) as typeof fetch diff --git a/desktop/src/lib/desktopRuntime.ts b/desktop/src/lib/desktopRuntime.ts index 082ebac9..0eeacc6d 100644 --- a/desktop/src/lib/desktopRuntime.ts +++ b/desktop/src/lib/desktopRuntime.ts @@ -1,4 +1,10 @@ -import { api, getDefaultBaseUrl, setAuthToken, setBaseUrl } from '../api/client' +import { + api, + getDefaultBaseUrl, + hasExplicitDefaultBaseUrl, + setAuthToken, + setBaseUrl, +} from '../api/client' export const H5_SERVER_URL_STORAGE_KEY = 'cc-haha-h5-server-url' export const H5_TOKEN_STORAGE_KEY = 'cc-haha-h5-token' @@ -133,7 +139,7 @@ async function initializeBrowserServerUrl(fallbackUrl: string) { const requestedUrl = normalizeServerUrl(queryUrl) ?? stored.serverUrl ?? - getSameOriginServerUrl() ?? + getConfiguredBrowserServerUrl(fallbackUrl) ?? fallbackUrl const token = stored.token const browserH5Runtime = requiresH5AuthForServerUrl(requestedUrl) @@ -249,6 +255,14 @@ function getSameOriginServerUrl() { return normalizeServerUrl(window.location.origin) } +function getConfiguredBrowserServerUrl(fallbackUrl: string) { + if (hasExplicitDefaultBaseUrl()) { + return normalizeServerUrl(fallbackUrl) + } + + return getSameOriginServerUrl() +} + export function isLoopbackHostname(hostname: string) { const normalized = hostname.trim().replace(/^\[/, '').replace(/\]$/, '').toLowerCase() return normalized === '127.0.0.1' || normalized === 'localhost' || normalized === '::1'