Skip to content

WebSocket Support

Expose fully supports WebSocket connections, allowing real-time applications to work through tunnels.

How It Works

When a visitor establishes a WebSocket connection to your tunnel URL:

  1. The Expose server receives the upgrade request
  2. It forwards the upgrade through the tunnel
  3. Your local server accepts the WebSocket
  4. All WebSocket frames are proxied bidirectionally
Browser Expose Server Your Local Server
│ │ │
├── WS Upgrade Request ───►│ │
│ ├── Forward Upgrade ───────►│
│ │◄── Accept Upgrade ────────┤
│◄── WS Connection ────────┤ │
│ │ │
├── WS Frame ─────────────►├───────────────────────────►
│◄─────────────────────────┤◄──────────────────────────┤

Supported Features

  • Text frames: JSON messages, chat, etc.
  • Binary frames: File uploads, media streaming
  • Ping/Pong: Connection keepalive
  • Close frames: Graceful disconnection

Example: Socket.io

Socket.io works through Expose tunnels:

Server (local):

const io = require('socket.io')(3000);
io.on('connection', (socket) => {
console.log('Client connected');
socket.on('message', (data) => {
socket.emit('response', { received: data });
});
});

Client (browser):

const socket = io('https://myapp.expose.yourdomain.com');
socket.on('connect', () => {
console.log('Connected to server');
socket.emit('message', 'Hello!');
});
socket.on('response', (data) => {
console.log('Received:', data);
});

Example: Native WebSocket

Server (local):

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
ws.send(`Echo: ${message}`);
});
});

Client:

const ws = new WebSocket('wss://myapp.expose.yourdomain.com');
ws.onopen = () => {
ws.send('Hello!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};

Limitations

Connection Limits

Each WebSocket connection uses resources on the tunnel. Very high numbers of concurrent connections may impact performance.

Latency

WebSocket frames travel through your VPS, adding some latency compared to direct connections. For most applications, this is negligible.

Timeouts

Long-idle WebSocket connections may be closed by:

  • Your server’s timeout settings
  • Network equipment
  • The Expose keepalive (30 second pings)

Implement reconnection logic in your client code.

Troubleshooting

Connection Fails to Upgrade

  • Ensure your local server supports WebSocket
  • Check the correct port is exposed
  • Verify the path matches your server’s WebSocket endpoint

Messages Not Received

  • Check browser console for errors
  • Verify the tunnel is connected
  • Test locally first without the tunnel

Frequent Disconnections

  • Implement reconnection logic
  • Check network stability
  • Monitor tunnel metrics for issues