WebSocket-to-TCP Proxy
Connect browsers to native Cap'n Proto services (C++, etc.) via WebSocket.
Overview
Browsers can only use WebSocket, while native Cap'n Proto services use raw TCP. This proxy bridges the two:
Browser ──WebSocket──→ Proxy ──TCP──→ C++ Cap'n Proto ServiceQuick Start
1. Start Your Cap'n Proto Service
For example, a C++ service on port 7000:
bash
./my-cpp-capnp-server --port 70002. Start the Proxy
bash
npx @naeemo/capnp proxy -p 9000 -t localhost:7000Options:
-p, --ws-port: WebSocket server port (default: 8080)-t, --target: Target TCP service (default: localhost:8081)-d, --debug: Enable debug logging
3. Connect from Browser
typescript
import { RpcConnection, WebSocketTransport } from '@naeemo/capnp';
import { MyService } from './my-service.js';
// Connect via proxy
const transport = await WebSocketTransport.connect('ws://localhost:9000');
const connection = new RpcConnection(transport);
// Use the service as if directly connected
const service = await connection.bootstrap().getAs(MyService);
const result = await service.myMethod({ data: 'hello' });Programmatic Usage
typescript
import { CapnpWebSocketProxy } from '@naeemo/capnp';
const proxy = new CapnpWebSocketProxy({
wsPort: 9000,
targetHost: 'localhost',
targetPort: 7000,
maxMessageSize: 16 * 1024 * 1024, // 16MB
connectionTimeout: 30000, // 30 seconds
debug: true,
});
// Monitor connections
proxy.on('connection', (conn) => {
console.log('New connection');
});
proxy.on('disconnection', (conn) => {
console.log('Connection closed');
console.log('Stats:', conn.getStats());
});
// Shutdown
await proxy.close();Architecture
Message Flow
- Browser → Proxy: WebSocket binary message
- Proxy → TCP Service: Raw bytes (no modification)
- TCP Service → Proxy: Raw bytes
- Proxy → Browser: WebSocket binary message
Protocol Compatibility
| Feature | Browser | Proxy | TCP Service |
|---|---|---|---|
| Transport | WebSocket | Bridge | TCP |
| Framing | WebSocket frames | Passthrough | Cap'n Proto messages |
| Binary | ✅ | ✅ | ✅ |
| Full-duplex | ✅ | ✅ | ✅ |
Use Cases
Web Dashboard for Native Service
typescript
// Browser: Real-time metrics from C++ backend
const transport = await WebSocketTransport.connect('ws://proxy:9000');
const metrics = await connection.bootstrap().getAs(MetricsService);
// Stream real-time data
for await (const update of metrics.subscribe()) {
updateChart(update);
}Cross-Language RPC
typescript
// Browser (TypeScript) calling Python service
// Browser → Proxy → Python Cap'n Proto Server
const transport = await WebSocketTransport.connect('ws://proxy:9000');
const pythonService = await connection.bootstrap().getAs(PythonService);Development & Debugging
bash
# Proxy local C++ service for browser dev tools
npx @naeemo/capnp proxy -p 9000 -t localhost:7000 --debugPerformance
| Metric | Value |
|---|---|
| Latency overhead | ~1-2ms |
| Throughput | 900+ MB/s |
| Concurrent connections | 1000+ |
| Message size limit | Configurable (default 16MB) |
Security Considerations
CORS: Proxy accepts connections from any origin. Deploy behind a reverse proxy (nginx, etc.) for production.
TLS: Use WSS (WebSocket Secure) in production:
Browser ──WSS──→ nginx ──WS──→ Proxy ──TCP──→ ServiceAuthentication: Implement auth at the application layer (Cap'n Proto capabilities) or use a token in the WebSocket URL.
Troubleshooting
Connection Refused
Check that the target TCP service is running:
bash
telnet localhost 7000Large Messages Fail
Increase the max message size:
typescript
const proxy = new CapnpWebSocketProxy({
wsPort: 9000,
targetHost: 'localhost',
targetPort: 7000,
maxMessageSize: 64 * 1024 * 1024, // 64MB
});Debug Mode
Enable verbose logging:
bash
npx @naeemo/capnp proxy -p 9000 -t localhost:7000 --debugExample: Complete Setup
See examples/websocket-proxy for a complete working example with:
- C++ Cap'n Proto server
- WebSocket-to-TCP proxy
- Browser client
API Reference
CapnpWebSocketProxy
Main proxy class.
Constructor
typescript
new CapnpWebSocketProxy(options: ProxyOptions)Methods
getConnectionCount(): number- Active connectionsgetAllStats(): ConnectionStats[]- Stats for all connectionsclose(): Promise<void>- Graceful shutdown
Events
connection- New client connecteddisconnection- Client disconnectederror- Error occurred
ProxyOptions
| Option | Type | Default | Description |
|---|---|---|---|
wsPort | number | required | WebSocket server port |
targetHost | string | required | Target TCP host |
targetPort | number | required | Target TCP port |
maxMessageSize | number | 16MB | Max WebSocket message size |
connectionTimeout | number | 30000 | TCP connection timeout (ms) |
debug | boolean | false | Enable debug logging |