mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-03 00:17:47 +00:00
fix(cliproxy): clear stale cleanup timer and fix session/tunnel edge cases
- Stop cleanup interval when all auth sessions are removed (unregister, cancel, cancelAll) so the Node event loop isn't held alive. - getActiveSessionForProvider now returns the most recent session by startedAt instead of the first map entry. - HTTPS tunnel includes port in Host header when non-443.
This commit is contained in:
@@ -39,14 +39,18 @@ function startCleanupInterval(): void {
|
|||||||
authSessionEvents.emit('session:expired', sessionId);
|
authSessionEvents.emit('session:expired', sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Stop interval if no active sessions
|
stopCleanupIfEmpty();
|
||||||
if (activeSessions.size === 0 && cleanupInterval) {
|
|
||||||
clearInterval(cleanupInterval);
|
|
||||||
cleanupInterval = null;
|
|
||||||
}
|
|
||||||
}, 60000); // Check every minute
|
}, 60000); // Check every minute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Clear the cleanup interval when no sessions remain. */
|
||||||
|
function stopCleanupIfEmpty(): void {
|
||||||
|
if (activeSessions.size === 0 && cleanupInterval) {
|
||||||
|
clearInterval(cleanupInterval);
|
||||||
|
cleanupInterval = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an active OAuth session
|
* Register an active OAuth session
|
||||||
*/
|
*/
|
||||||
@@ -82,6 +86,7 @@ export function attachProcessToSession(sessionId: string, process: ChildProcess)
|
|||||||
export function unregisterAuthSession(sessionId: string): void {
|
export function unregisterAuthSession(sessionId: string): void {
|
||||||
activeSessions.delete(sessionId);
|
activeSessions.delete(sessionId);
|
||||||
authSessionEvents.emit('session:ended', sessionId);
|
authSessionEvents.emit('session:ended', sessionId);
|
||||||
|
stopCleanupIfEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,6 +106,7 @@ export function cancelAuthSession(sessionId: string): boolean {
|
|||||||
|
|
||||||
activeSessions.delete(sessionId);
|
activeSessions.delete(sessionId);
|
||||||
authSessionEvents.emit('session:cancelled', sessionId);
|
authSessionEvents.emit('session:cancelled', sessionId);
|
||||||
|
stopCleanupIfEmpty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,15 +118,16 @@ export function getActiveSession(sessionId: string): ActiveAuthSession | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get active session for a provider (most recent)
|
* Get active session for a provider (most recent by startedAt)
|
||||||
*/
|
*/
|
||||||
export function getActiveSessionForProvider(provider: string): ActiveAuthSession | null {
|
export function getActiveSessionForProvider(provider: string): ActiveAuthSession | null {
|
||||||
|
let latest: ActiveAuthSession | null = null;
|
||||||
for (const session of activeSessions.values()) {
|
for (const session of activeSessions.values()) {
|
||||||
if (session.provider === provider) {
|
if (session.provider === provider && (!latest || session.startedAt > latest.startedAt)) {
|
||||||
return session;
|
latest = session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,5 +152,6 @@ export function cancelAllSessionsForProvider(provider: string): number {
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stopCleanupIfEmpty();
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,8 +162,12 @@ export class HttpsTunnelProxy {
|
|||||||
headers[key] = value;
|
headers[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set correct host header for remote
|
// Set correct host header for remote (include port when non-default)
|
||||||
headers['Host'] = this.config.remoteHost;
|
if (this.config.remotePort === 443) {
|
||||||
|
headers['Host'] = this.config.remoteHost;
|
||||||
|
} else {
|
||||||
|
headers['Host'] = `${this.config.remoteHost}:${this.config.remotePort}`;
|
||||||
|
}
|
||||||
|
|
||||||
// Inject Authorization header if not present but authToken is configured
|
// Inject Authorization header if not present but authToken is configured
|
||||||
// This is a fallback - normally the client (CodexReasoningProxy) forwards the header
|
// This is a fallback - normally the client (CodexReasoningProxy) forwards the header
|
||||||
|
|||||||
Reference in New Issue
Block a user