From d0599e8d2c990ad02b270b8ada700db2d1d2e510 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Sun, 21 Dec 2025 04:13:36 -0500 Subject: [PATCH] feat(cliproxy): add localhost URL rewriting for remote proxy mode - Add rewriteLocalhostUrls() to detect and rewrite localhost URLs - Support 127.0.0.1, localhost, 0.0.0.0 patterns - Update getEffectiveEnvVars() to accept remoteRewriteConfig param - Auto-rewrite saved settings URLs to remote server at runtime --- src/cliproxy/config-generator.ts | 63 ++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/src/cliproxy/config-generator.ts b/src/cliproxy/config-generator.ts index d0ca4b95..5ce6ac86 100644 --- a/src/cliproxy/config-generator.ts +++ b/src/cliproxy/config-generator.ts @@ -392,6 +392,48 @@ function getGlobalEnvVars(): Record { return globalEnvConfig.env; } +/** Remote proxy configuration for URL rewriting */ +interface RemoteProxyRewriteConfig { + host: string; + port?: number; + protocol: 'http' | 'https'; + authToken?: string; +} + +/** + * Rewrite localhost URLs to remote server URLs. + * Handles various localhost patterns: 127.0.0.1, localhost, 0.0.0.0 + */ +function rewriteLocalhostUrls( + envVars: NodeJS.ProcessEnv, + provider: CLIProxyProvider, + remoteConfig: RemoteProxyRewriteConfig +): NodeJS.ProcessEnv { + const result = { ...envVars }; + const baseUrl = result.ANTHROPIC_BASE_URL; + + if (!baseUrl) return result; + + // Check if URL points to localhost (127.0.0.1, localhost, 0.0.0.0) + const localhostPattern = /^https?:\/\/(127\.0\.0\.1|localhost|0\.0\.0\.0)(:\d+)?/i; + if (!localhostPattern.test(baseUrl)) return result; + + // Build remote URL with smart port handling + const defaultPort = remoteConfig.protocol === 'https' ? 443 : 80; + const effectivePort = remoteConfig.port ?? defaultPort; + const portSuffix = effectivePort === defaultPort ? '' : `:${effectivePort}`; + const remoteBaseUrl = `${remoteConfig.protocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`; + + result.ANTHROPIC_BASE_URL = remoteBaseUrl; + + // Update auth token if provided + if (remoteConfig.authToken) { + result.ANTHROPIC_AUTH_TOKEN = remoteConfig.authToken; + } + + return result; +} + /** * Get effective environment variables for provider * @@ -402,15 +444,20 @@ function getGlobalEnvVars(): Record { * * All results are merged with global_env vars (telemetry/reporting disables). * User takes full responsibility for custom settings. + * + * If remoteRewriteConfig is provided, localhost URLs are rewritten to remote server. */ export function getEffectiveEnvVars( provider: CLIProxyProvider, port: number = CLIPROXY_DEFAULT_PORT, - customSettingsPath?: string + customSettingsPath?: string, + remoteRewriteConfig?: RemoteProxyRewriteConfig ): NodeJS.ProcessEnv { // Get global env vars (DISABLE_TELEMETRY, etc.) const globalEnv = getGlobalEnvVars(); + let envVars: NodeJS.ProcessEnv; + // Priority 1: Custom settings path (for user-defined variants) if (customSettingsPath) { const expandedPath = customSettingsPath.replace(/^~/, require('os').homedir()); @@ -421,7 +468,12 @@ export function getEffectiveEnvVars( if (settings.env && typeof settings.env === 'object') { // Custom variant settings found - merge with global env - return { ...globalEnv, ...settings.env }; + envVars = { ...globalEnv, ...settings.env }; + // Apply remote rewrite if configured + if (remoteRewriteConfig) { + envVars = rewriteLocalhostUrls(envVars, provider, remoteRewriteConfig); + } + return envVars; } } catch { // Invalid JSON - fall through to provider defaults @@ -443,7 +495,12 @@ export function getEffectiveEnvVars( if (settings.env && typeof settings.env === 'object') { // User override found - merge with global env - return { ...globalEnv, ...settings.env }; + envVars = { ...globalEnv, ...settings.env }; + // Apply remote rewrite if configured + if (remoteRewriteConfig) { + envVars = rewriteLocalhostUrls(envVars, provider, remoteRewriteConfig); + } + return envVars; } } catch { // Invalid JSON or structure - fall through to defaults