Skip to main content
POST
/
conn
/
kick
curl -X POST "http://localhost:5001/conn/kick" \
  -H "Content-Type: application/json" \
  -d '{
    "uid": "user123",
    "conn_id": 12345,
    "node_id": 1
  }'
{
  "status": "ok"
}

Overview

Kick/disconnect a specific connection for a specified user. Similar to removing connections, but typically used for actively disconnecting live connections.

Request Body

Required Parameters

uid
string
required
User ID
conn_id
integer
required
Connection ID

Optional Parameters

node_id
integer
Node ID, specifies connection on a specific node
curl -X POST "http://localhost:5001/conn/kick" \
  -H "Content-Type: application/json" \
  -d '{
    "uid": "user123",
    "conn_id": 12345,
    "node_id": 1
  }'
{
  "status": "ok"
}

Response Fields

status
string
required
Operation status, returns "ok" on success

Status Codes

Status CodeDescription
200Connection kicked successfully
400Request parameter error
404Connection does not exist
500Internal server error

Difference from Remove Connection

OperationEndpointPurposeCharacteristics
Kick Connection/conn/kickActively disconnect live connectionsSends disconnect notification to client
Remove Connection/conn/removeClean up connection recordsDirectly cleans server-side connection records

Use Cases

User Session Management

Force User Logout:
// Force logout a user from specific device
async function forceUserLogout(userId, connectionId, nodeId, reason = 'admin_action') {
    try {
        // Log the action
        await logAdminAction({
            action: 'force_logout',
            target_user: userId,
            connection_id: connectionId,
            node_id: nodeId,
            reason: reason,
            timestamp: new Date().toISOString()
        });
        
        // Kick the connection
        await kickConnection({
            uid: userId,
            conn_id: connectionId,
            node_id: nodeId
        });
        
        // Notify user about forced logout
        await sendNotificationToUser(userId, {
            type: 'forced_logout',
            reason: reason,
            timestamp: new Date().toISOString()
        });
        
        console.log(`User ${userId} forcibly logged out from connection ${connectionId}`);
    } catch (error) {
        console.error('Failed to force user logout:', error);
    }
}
Session Timeout Management:
// Manage session timeouts
class SessionTimeoutManager {
    constructor(timeoutMinutes = 30) {
        this.timeoutDuration = timeoutMinutes * 60 * 1000;
        this.activeSessions = new Map();
        this.checkInterval = 60000; // Check every minute
    }
    
    startMonitoring() {
        this.monitoringInterval = setInterval(() => {
            this.checkExpiredSessions();
        }, this.checkInterval);
        
        console.log('Session timeout monitoring started');
    }
    
    stopMonitoring() {
        if (this.monitoringInterval) {
            clearInterval(this.monitoringInterval);
            this.monitoringInterval = null;
        }
        console.log('Session timeout monitoring stopped');
    }
    
    updateSessionActivity(userId, connectionId, nodeId) {
        const sessionKey = `${userId}:${connectionId}:${nodeId}`;
        this.activeSessions.set(sessionKey, {
            userId,
            connectionId,
            nodeId,
            lastActivity: Date.now()
        });
    }
    
    async checkExpiredSessions() {
        const now = Date.now();
        const expiredSessions = [];
        
        for (const [sessionKey, session] of this.activeSessions) {
            const timeSinceActivity = now - session.lastActivity;
            
            if (timeSinceActivity > this.timeoutDuration) {
                expiredSessions.push(session);
                this.activeSessions.delete(sessionKey);
            }
        }
        
        // Kick expired sessions
        for (const session of expiredSessions) {
            try {
                await this.kickExpiredSession(session);
            } catch (error) {
                console.error(`Failed to kick expired session for user ${session.userId}:`, error);
            }
        }
        
        if (expiredSessions.length > 0) {
            console.log(`Kicked ${expiredSessions.length} expired sessions`);
        }
    }
    
    async kickExpiredSession(session) {
        await kickConnection({
            uid: session.userId,
            conn_id: session.connectionId,
            node_id: session.nodeId
        });
        
        // Log timeout event
        await logSessionEvent({
            type: 'session_timeout',
            user_id: session.userId,
            connection_id: session.connectionId,
            node_id: session.nodeId,
            last_activity: new Date(session.lastActivity).toISOString(),
            timeout_duration_minutes: this.timeoutDuration / 60000
        });
    }
    
    getActiveSessionCount() {
        return this.activeSessions.size;
    }
}

// Usage
const sessionManager = new SessionTimeoutManager(30); // 30 minute timeout
sessionManager.startMonitoring();

// Update activity when user performs actions
sessionManager.updateSessionActivity('user123', 12345, 1);

Security Management

Suspicious Activity Response:
// Kick connections showing suspicious activity
async function handleSuspiciousActivity(userId, connectionId, nodeId, activityType) {
    try {
        // Log security incident
        const incidentId = await logSecurityIncident({
            type: 'suspicious_activity',
            user_id: userId,
            connection_id: connectionId,
            node_id: nodeId,
            activity_type: activityType,
            timestamp: new Date().toISOString(),
            action_taken: 'connection_kicked'
        });
        
        // Kick the suspicious connection
        await kickConnection({
            uid: userId,
            conn_id: connectionId,
            node_id: nodeId
        });
        
        // Notify security team
        await notifySecurityTeam({
            incident_id: incidentId,
            user_id: userId,
            connection_id: connectionId,
            activity_type: activityType,
            action: 'Connection kicked due to suspicious activity'
        });
        
        // Temporarily block user if needed
        if (activityType === 'multiple_failed_auth' || activityType === 'rate_limit_exceeded') {
            await temporarilyBlockUser(userId, 15); // 15 minute block
        }
        
        console.log(`Kicked suspicious connection ${connectionId} for user ${userId}`);
    } catch (error) {
        console.error('Failed to handle suspicious activity:', error);
    }
}

Administrative Control

Bulk Connection Management:
// Kick multiple connections for administrative purposes
async function bulkKickConnections(connections, reason = 'admin_maintenance') {
    const results = [];
    
    for (const conn of connections) {
        try {
            await kickConnection({
                uid: conn.uid,
                conn_id: conn.conn_id,
                node_id: conn.node_id
            });
            
            results.push({
                uid: conn.uid,
                conn_id: conn.conn_id,
                success: true
            });
            
            // Small delay to avoid overwhelming the system
            await new Promise(resolve => setTimeout(resolve, 100));
        } catch (error) {
            results.push({
                uid: conn.uid,
                conn_id: conn.conn_id,
                success: false,
                error: error.message
            });
        }
    }
    
    // Log bulk operation
    await logAdminAction({
        action: 'bulk_kick_connections',
        reason: reason,
        total_connections: connections.length,
        successful_kicks: results.filter(r => r.success).length,
        failed_kicks: results.filter(r => !r.success).length,
        timestamp: new Date().toISOString()
    });
    
    return results;
}

Maintenance Operations

Graceful Node Shutdown:
// Gracefully kick all connections from a node before shutdown
async function gracefulNodeShutdown(nodeId, notificationMessage = 'Server maintenance in progress') {
    try {
        // Get all connections on the node
        const nodeConnections = await getNodeConnections(nodeId);
        
        console.log(`Starting graceful shutdown for node ${nodeId} (${nodeConnections.length} connections)`);
        
        // Send notification to all users first
        for (const conn of nodeConnections) {
            try {
                await sendMaintenanceNotification(conn.uid, {
                    message: notificationMessage,
                    estimated_downtime: '10-15 minutes',
                    reconnect_instructions: 'Please reconnect in a few minutes'
                });
            } catch (error) {
                console.error(`Failed to notify user ${conn.uid}:`, error);
            }
        }
        
        // Wait a bit for notifications to be delivered
        await new Promise(resolve => setTimeout(resolve, 5000));
        
        // Kick connections in batches
        const batchSize = 10;
        const batches = chunkArray(nodeConnections, batchSize);
        
        for (let i = 0; i < batches.length; i++) {
            const batch = batches[i];
            console.log(`Kicking batch ${i + 1}/${batches.length}`);
            
            const batchResults = await bulkKickConnections(batch, 'node_maintenance');
            
            // Wait between batches
            if (i < batches.length - 1) {
                await new Promise(resolve => setTimeout(resolve, 2000));
            }
        }
        
        console.log(`Graceful shutdown completed for node ${nodeId}`);
    } catch (error) {
        console.error(`Graceful shutdown failed for node ${nodeId}:`, error);
    }
}

Connection Quality Management

Poor Connection Cleanup:
// Kick connections with poor quality metrics
class ConnectionQualityManager {
    constructor() {
        this.qualityThresholds = {
            maxLatency: 5000, // 5 seconds
            minHeartbeatInterval: 60000, // 1 minute
            maxFailedPings: 3
        };
    }
    
    async monitorAndKickPoorConnections() {
        try {
            const allConnections = await getAllActiveConnections();
            const poorConnections = [];
            
            for (const conn of allConnections) {
                const quality = await this.assessConnectionQuality(conn);
                
                if (!quality.isGood) {
                    poorConnections.push({
                        connection: conn,
                        quality: quality
                    });
                }
            }
            
            // Kick poor quality connections
            for (const poor of poorConnections) {
                await this.kickPoorConnection(poor.connection, poor.quality);
            }
            
            return {
                total_checked: allConnections.length,
                poor_connections: poorConnections.length,
                kicked: poorConnections.length
            };
        } catch (error) {
            console.error('Connection quality monitoring failed:', error);
            return { error: error.message };
        }
    }
    
    async assessConnectionQuality(connection) {
        const metrics = await getConnectionMetrics(connection.conn_id);
        
        const issues = [];
        
        if (metrics.latency > this.qualityThresholds.maxLatency) {
            issues.push(`High latency: ${metrics.latency}ms`);
        }
        
        if (metrics.lastHeartbeat && 
            Date.now() - metrics.lastHeartbeat > this.qualityThresholds.minHeartbeatInterval) {
            issues.push('Missed heartbeat');
        }
        
        if (metrics.failedPings > this.qualityThresholds.maxFailedPings) {
            issues.push(`Too many failed pings: ${metrics.failedPings}`);
        }
        
        return {
            isGood: issues.length === 0,
            issues: issues,
            metrics: metrics
        };
    }
    
    async kickPoorConnection(connection, quality) {
        try {
            await kickConnection({
                uid: connection.uid,
                conn_id: connection.conn_id,
                node_id: connection.node_id
            });
            
            // Log quality issue
            await logConnectionQualityEvent({
                user_id: connection.uid,
                connection_id: connection.conn_id,
                node_id: connection.node_id,
                quality_issues: quality.issues,
                metrics: quality.metrics,
                action: 'connection_kicked',
                timestamp: new Date().toISOString()
            });
            
            console.log(`Kicked poor quality connection ${connection.conn_id} for user ${connection.uid}`);
        } catch (error) {
            console.error(`Failed to kick poor connection ${connection.conn_id}:`, error);
        }
    }
}

// Usage
const qualityManager = new ConnectionQualityManager();

// Run quality check every 5 minutes
setInterval(async () => {
    const result = await qualityManager.monitorAndKickPoorConnections();
    if (result.kicked > 0) {
        console.log(`Quality check: kicked ${result.kicked} poor connections`);
    }
}, 5 * 60 * 1000);

Best Practices

  1. Graceful Notification: Send notifications to users before kicking connections when possible
  2. Logging: Log all kick operations with reasons for audit purposes
  3. Rate Limiting: Avoid kicking too many connections simultaneously
  4. Error Handling: Handle kick failures gracefully
  5. User Experience: Provide clear reconnection instructions to affected users
  6. Security: Use kick operations as part of security incident response
  7. Monitoring: Monitor kick operations to identify patterns or issues