mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 12:19:35 +00:00
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:
@@ -62,6 +62,41 @@ function ensureRequiredEnvVars(
|
|||||||
/** Default CLIProxy port */
|
/** Default CLIProxy port */
|
||||||
export const CLIPROXY_DEFAULT_PORT = 8317;
|
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 */
|
/** Internal API key for CCS-managed requests */
|
||||||
export const CCS_INTERNAL_API_KEY = 'ccs-internal-managed';
|
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;
|
const localhostPattern = /^https?:\/\/(127\.0\.0\.1|localhost|0\.0\.0\.0)(:\d+)?/i;
|
||||||
if (!localhostPattern.test(baseUrl)) return result;
|
if (!localhostPattern.test(baseUrl)) return result;
|
||||||
|
|
||||||
// Build remote URL with smart port handling
|
// Build remote URL with smart port handling (8317 for HTTP, 443 for HTTPS)
|
||||||
const defaultPort = remoteConfig.protocol === 'https' ? 443 : 80;
|
// Validate port and normalize protocol for defensive handling
|
||||||
const effectivePort = remoteConfig.port ?? defaultPort;
|
const normalizedProtocol = normalizeProtocol(remoteConfig.protocol);
|
||||||
const portSuffix = effectivePort === defaultPort ? '' : `:${effectivePort}`;
|
const validatedPort = validateRemotePort(remoteConfig.port);
|
||||||
const remoteBaseUrl = `${remoteConfig.protocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`;
|
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;
|
result.ANTHROPIC_BASE_URL = remoteBaseUrl;
|
||||||
|
|
||||||
@@ -686,11 +725,15 @@ export function getRemoteEnvVars(
|
|||||||
remoteConfig: { host: string; port?: number; protocol: 'http' | 'https'; authToken?: string },
|
remoteConfig: { host: string; port?: number; protocol: 'http' | 'https'; authToken?: string },
|
||||||
customSettingsPath?: string
|
customSettingsPath?: string
|
||||||
): Record<string, string> {
|
): Record<string, string> {
|
||||||
// Build URL with smart port handling - omit if using protocol default
|
// Build URL with smart port handling (8317 for HTTP, 443 for HTTPS)
|
||||||
const defaultPort = remoteConfig.protocol === 'https' ? 443 : 80;
|
// Validate port and normalize protocol for defensive handling
|
||||||
const effectivePort = remoteConfig.port ?? defaultPort;
|
const normalizedProtocol = normalizeProtocol(remoteConfig.protocol);
|
||||||
const portSuffix = effectivePort === defaultPort ? '' : `:${effectivePort}`;
|
const validatedPort = validateRemotePort(remoteConfig.port);
|
||||||
const baseUrl = `${remoteConfig.protocol}://${remoteConfig.host}${portSuffix}/api/provider/${provider}`;
|
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.)
|
// Get global env vars (DISABLE_TELEMETRY, etc.)
|
||||||
const globalEnv = getGlobalEnvVars();
|
const globalEnv = getGlobalEnvVars();
|
||||||
|
|||||||
@@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
|
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
|
||||||
import type { CliproxyServerConfig } from '../config/unified-config-types';
|
import type { CliproxyServerConfig } from '../config/unified-config-types';
|
||||||
|
import {
|
||||||
/** Default CLIProxyAPI port */
|
CLIPROXY_DEFAULT_PORT,
|
||||||
const DEFAULT_CLIPROXY_PORT = 8317;
|
getRemoteDefaultPort,
|
||||||
|
normalizeProtocol,
|
||||||
|
validateRemotePort,
|
||||||
|
} from './config-generator';
|
||||||
|
|
||||||
/** Resolved proxy target for making requests */
|
/** Resolved proxy target for making requests */
|
||||||
export interface ProxyTarget {
|
export interface ProxyTarget {
|
||||||
@@ -42,10 +45,11 @@ export function getProxyTarget(): ProxyTarget {
|
|||||||
const config = loadCliproxyServerConfig();
|
const config = loadCliproxyServerConfig();
|
||||||
|
|
||||||
if (config?.remote?.enabled && config.remote?.host) {
|
if (config?.remote?.enabled && config.remote?.host) {
|
||||||
const protocol = config.remote.protocol ?? 'http';
|
// Normalize protocol (handles case sensitivity and invalid values)
|
||||||
// Default port based on protocol if not specified
|
const protocol = normalizeProtocol(config.remote.protocol);
|
||||||
const defaultPort = protocol === 'https' ? 443 : 80;
|
// Validate port (returns undefined for invalid, triggering default)
|
||||||
const port = config.remote.port ?? defaultPort;
|
const validatedPort = validateRemotePort(config.remote.port);
|
||||||
|
const port = validatedPort ?? getRemoteDefaultPort(protocol);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
host: config.remote.host,
|
host: config.remote.host,
|
||||||
@@ -58,7 +62,7 @@ export function getProxyTarget(): ProxyTarget {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
port: config?.local?.port ?? DEFAULT_CLIPROXY_PORT,
|
port: config?.local?.port ?? CLIPROXY_DEFAULT_PORT,
|
||||||
protocol: 'http',
|
protocol: 'http',
|
||||||
isRemote: false,
|
isRemote: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
|
import { getRemoteDefaultPort, validateRemotePort } from './config-generator';
|
||||||
|
|
||||||
/** Error codes for remote proxy status */
|
/** Error codes for remote proxy status */
|
||||||
export type RemoteProxyErrorCode =
|
export type RemoteProxyErrorCode =
|
||||||
@@ -52,17 +53,6 @@ export interface RemoteProxyClientConfig {
|
|||||||
/** Default timeout for remote proxy requests (aggressive for CLI UX) */
|
/** Default timeout for remote proxy requests (aggressive for CLI UX) */
|
||||||
const DEFAULT_TIMEOUT_MS = 2000;
|
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)
|
* Get standard web port for protocol (for URL display omission)
|
||||||
* These are the ports that browsers/HTTP clients use by default.
|
* 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.
|
* 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 {
|
function getEffectivePort(port: number | undefined, protocol: 'http' | 'https'): number {
|
||||||
return port ?? getDefaultPort(protocol);
|
const validatedPort = validateRemotePort(port);
|
||||||
|
return validatedPort ?? getRemoteDefaultPort(protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user