fix(cliproxy): use correct default port (8317) for remote HTTP connections

Root cause: Inconsistent default port logic across code paths.
- Test Connection used 8317 (correct)
- Actual API calls used 80 (wrong)

Changes:
- Add centralized getRemoteDefaultPort() helper in config-generator.ts
- Fix proxy-target-resolver.ts to use shared helper
- Fix rewriteLocalhostUrls() and getRemoteEnvVars() in config-generator.ts
- Update remote-proxy-client.ts to use shared helper (DRY)

Fixes all 3 reported issues:
1. Port empty → now correctly uses :8317 instead of :80
2. BASEURL construction → now includes correct port
3. CLIProxy Plus auth → now fetches from remote on correct port
This commit is contained in:
kaitranntt
2025-12-30 16:03:09 -05:00
parent 59928c106b
commit 76aab09616
3 changed files with 69 additions and 31 deletions
+53 -10
View File
@@ -62,6 +62,41 @@ function ensureRequiredEnvVars(
/** Default CLIProxy port */
export const CLIPROXY_DEFAULT_PORT = 8317;
/**
* Normalize protocol to lowercase and validate.
* Handles runtime case sensitivity (e.g., 'HTTPS' → 'https').
* Defaults to 'http' for invalid values.
*/
export function normalizeProtocol(protocol: string | undefined): 'http' | 'https' {
if (!protocol) return 'http';
const normalized = protocol.toLowerCase();
if (normalized === 'https') return 'https';
if (normalized === 'http') return 'http';
// Invalid protocol (e.g., 'ftp') - default to http
return 'http';
}
/**
* Validate and sanitize port number for remote connections.
* Returns undefined for invalid ports (letting caller use default).
* Valid range: 1-65535, must be integer.
*/
export function validateRemotePort(port: number | undefined): number | undefined {
if (port === undefined || port === null) return undefined;
if (typeof port !== 'number' || !Number.isInteger(port)) return undefined;
if (port <= 0 || port > 65535) return undefined;
return port;
}
/**
* Get default port for remote CLIProxyAPI based on protocol.
* - HTTP: 8317 (CLIProxyAPI default)
* - HTTPS: 443 (standard SSL port)
*/
export function getRemoteDefaultPort(protocol: 'http' | 'https'): number {
return protocol === 'https' ? 443 : CLIPROXY_DEFAULT_PORT;
}
/** Internal API key for CCS-managed requests */
export const CCS_INTERNAL_API_KEY = 'ccs-internal-managed';
@@ -548,11 +583,15 @@ function rewriteLocalhostUrls(
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}`;
// Build remote URL with smart port handling (8317 for HTTP, 443 for HTTPS)
// Validate port and normalize protocol for defensive handling
const normalizedProtocol = normalizeProtocol(remoteConfig.protocol);
const validatedPort = validateRemotePort(remoteConfig.port);
const effectivePort = validatedPort ?? getRemoteDefaultPort(normalizedProtocol);
// Omit port suffix for standard web ports (80/443) for cleaner URLs
const standardWebPort = normalizedProtocol === 'https' ? 443 : 80;
const portSuffix = effectivePort === standardWebPort ? '' : `:${effectivePort}`;
const remoteBaseUrl = `${normalizedProtocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`;
result.ANTHROPIC_BASE_URL = remoteBaseUrl;
@@ -686,11 +725,15 @@ export function getRemoteEnvVars(
remoteConfig: { host: string; port?: number; protocol: 'http' | 'https'; authToken?: string },
customSettingsPath?: string
): Record<string, string> {
// Build URL with smart port handling - omit if using protocol default
const defaultPort = remoteConfig.protocol === 'https' ? 443 : 80;
const effectivePort = remoteConfig.port ?? defaultPort;
const portSuffix = effectivePort === defaultPort ? '' : `:${effectivePort}`;
const baseUrl = `${remoteConfig.protocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`;
// Build URL with smart port handling (8317 for HTTP, 443 for HTTPS)
// Validate port and normalize protocol for defensive handling
const normalizedProtocol = normalizeProtocol(remoteConfig.protocol);
const validatedPort = validateRemotePort(remoteConfig.port);
const effectivePort = validatedPort ?? getRemoteDefaultPort(normalizedProtocol);
// Omit port suffix for standard web ports (80/443) for cleaner URLs
const standardWebPort = normalizedProtocol === 'https' ? 443 : 80;
const portSuffix = effectivePort === standardWebPort ? '' : `:${effectivePort}`;
const baseUrl = `${normalizedProtocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`;
// Get global env vars (DISABLE_TELEMETRY, etc.)
const globalEnv = getGlobalEnvVars();
+12 -8
View File
@@ -7,9 +7,12 @@
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
import type { CliproxyServerConfig } from '../config/unified-config-types';
/** Default CLIProxyAPI port */
const DEFAULT_CLIPROXY_PORT = 8317;
import {
CLIPROXY_DEFAULT_PORT,
getRemoteDefaultPort,
normalizeProtocol,
validateRemotePort,
} from './config-generator';
/** Resolved proxy target for making requests */
export interface ProxyTarget {
@@ -42,10 +45,11 @@ export function getProxyTarget(): ProxyTarget {
const config = loadCliproxyServerConfig();
if (config?.remote?.enabled && config.remote?.host) {
const protocol = config.remote.protocol ?? 'http';
// Default port based on protocol if not specified
const defaultPort = protocol === 'https' ? 443 : 80;
const port = config.remote.port ?? defaultPort;
// Normalize protocol (handles case sensitivity and invalid values)
const protocol = normalizeProtocol(config.remote.protocol);
// Validate port (returns undefined for invalid, triggering default)
const validatedPort = validateRemotePort(config.remote.port);
const port = validatedPort ?? getRemoteDefaultPort(protocol);
return {
host: config.remote.host,
@@ -58,7 +62,7 @@ export function getProxyTarget(): ProxyTarget {
return {
host: '127.0.0.1',
port: config?.local?.port ?? DEFAULT_CLIPROXY_PORT,
port: config?.local?.port ?? CLIPROXY_DEFAULT_PORT,
protocol: 'http',
isRemote: false,
};
+4 -13
View File
@@ -6,6 +6,7 @@
*/
import * as https from 'https';
import { getRemoteDefaultPort, validateRemotePort } from './config-generator';
/** Error codes for remote proxy status */
export type RemoteProxyErrorCode =
@@ -52,17 +53,6 @@ export interface RemoteProxyClientConfig {
/** Default timeout for remote proxy requests (aggressive for CLI UX) */
const DEFAULT_TIMEOUT_MS = 2000;
/**
* Get default port for CLIProxyAPI based on protocol.
* - HTTP: 8317 (CLIProxyAPI default for local/dev scenarios)
* - HTTPS: 443 (standard SSL port for production remote servers)
*
* This matches the UI labels shown to users.
*/
function getDefaultPort(protocol: 'http' | 'https'): number {
return protocol === 'https' ? 443 : 8317;
}
/**
* Get standard web port for protocol (for URL display omission)
* These are the ports that browsers/HTTP clients use by default.
@@ -74,10 +64,11 @@ function getStandardWebPort(protocol: 'http' | 'https'): number {
/**
* Get effective port for CLIProxyAPI connection.
* If port is provided, use it. Otherwise use protocol-based default.
* Validates port and uses protocol-based default for invalid/undefined values.
*/
function getEffectivePort(port: number | undefined, protocol: 'http' | 'https'): number {
return port ?? getDefaultPort(protocol);
const validatedPort = validateRemotePort(port);
return validatedPort ?? getRemoteDefaultPort(protocol);
}
/**