WebSocket API¶
Real-time bidirectional communication for interactive operations.
Overview¶
WebSocket provides full-duplex communication between the client and TFDrift-Falco backend, enabling real-time updates and interactive queries.
Endpoint: ws://localhost:8080/ws
Features¶
- ✅ Topic-based Subscriptions - Subscribe to specific event types
- ✅ Real-time Updates - Instant drift and event notifications
- ✅ Bidirectional Communication - Client can query, server can push
- ✅ Automatic Reconnection - Client libraries handle reconnection
- ✅ Heartbeat Mechanism - Ping/Pong to keep connection alive
Connection¶
JavaScript/TypeScript¶
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onopen = () => {
console.log('Connected to TFDrift WebSocket');
// Subscribe to drift alerts
ws.send(JSON.stringify({
type: 'subscribe',
topic: 'drifts'
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
if (message.type === 'drift') {
handleDriftAlert(message.payload);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('Disconnected');
// Implement reconnection logic
};
Using React Hook¶
import { useWebSocket } from './api/websocket';
function MyComponent() {
const {
isConnected,
lastMessage,
subscribe,
unsubscribe
} = useWebSocket();
useEffect(() => {
subscribe('drifts');
return () => unsubscribe('drifts');
}, []);
useEffect(() => {
if (lastMessage?.type === 'drift') {
console.log('New drift:', lastMessage.payload);
}
}, [lastMessage]);
return <div>Status: {isConnected ? 'Connected' : 'Disconnected'}</div>;
}
Message Format¶
Client → Server¶
{
"type": "subscribe" | "unsubscribe" | "ping" | "query",
"topic": "all" | "drifts" | "events" | "state" | "stats",
"payload": { ... }
}
Server → Client¶
{
"type": "drift" | "event" | "state_change" | "pong" | "welcome",
"topic": "drifts",
"timestamp": "2025-01-15T10:00:00Z",
"payload": { ... }
}
Message Types¶
Subscribe¶
Subscribe to a specific topic for real-time updates.
Available Topics: - all - All events - drifts - Drift alerts only - events - Falco events only - state - Terraform state changes - stats - Statistics updates
Unsubscribe¶
Ping (Heartbeat)¶
Response:
Server Events¶
Welcome¶
Sent immediately after connection.
{
"type": "welcome",
"payload": {
"message": "Connected to TFDrift-Falco WebSocket",
"client_id": "client-uuid-here"
}
}
Drift Alert¶
Real-time drift detection notification.
{
"type": "drift",
"topic": "drifts",
"timestamp": "2025-01-15T10:00:00Z",
"payload": {
"severity": "critical",
"resource_type": "aws_iam_policy",
"resource_id": "ANPAI23HZ27SI6FQMGNQ2",
"old_value": "...",
"new_value": "...",
"user": "john.doe@example.com"
}
}
Falco Event¶
Real-time Falco security event.
{
"type": "falco",
"topic": "events",
"timestamp": "2025-01-15T10:15:30Z",
"payload": {
"severity": "critical",
"rule": "Unauthorized Process Execution",
"output": "...",
"container_id": "abc123"
}
}
State Change¶
Terraform state modification notification.
{
"type": "state_change",
"topic": "state",
"timestamp": "2025-01-15T10:20:00Z",
"payload": {
"resource": "aws_iam_policy.example",
"action": "modified",
"serial": 43
}
}
Connection Management¶
Heartbeat¶
The server sends ping messages every 60 seconds. Clients should respond with pong within 54 seconds to maintain the connection.
Server → Client:
Client → Server:
Reconnection¶
Implement exponential backoff for reconnection:
let reconnectAttempts = 0;
const maxAttempts = 5;
function connect() {
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onclose = () => {
if (reconnectAttempts < maxAttempts) {
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
console.log(`Reconnecting in ${delay}ms...`);
setTimeout(connect, delay);
reconnectAttempts++;
}
};
ws.onopen = () => {
reconnectAttempts = 0; // Reset on successful connection
};
}
Error Handling¶
Connection Errors¶
ws.onerror = (error) => {
console.error('WebSocket error:', error);
// Log error details
// Attempt reconnection
};
Close Codes¶
Standard WebSocket close codes: - 1000 - Normal closure - 1001 - Going away (server shutdown) - 1002 - Protocol error - 1003 - Unsupported data - 1006 - Abnormal closure - 1008 - Policy violation
Best Practices¶
- Always implement reconnection logic
- Handle ping/pong for connection health
- Subscribe only to needed topics
- Buffer messages during disconnection
- Implement exponential backoff
- Clean up subscriptions on unmount
- Log connection events for debugging
Related Documentation¶
- REST API - HTTP-based API endpoints
- Server-Sent Events - Unidirectional streaming
- Frontend Integration - React hook usage
Last Updated: January 2025