Transport: WebSocket (persistent outbound from CLI to Edge)
Purpose: Multiplex HTTP and WebSocket traffic between Edge Gateway and localhost through a single tunnel connection.
All frames are binary over WebSocket. Each frame has a fixed header:
┌─────────────┬─────────────┬─────────────────────────────────┐
│ Type (1B) │ StreamID(4B)│ Payload (variable) │
└─────────────┴─────────────┴─────────────────────────────────┘
- Type: 1 byte, frame type identifier
- StreamID: 4 bytes, big-endian uint32. 0x00000000 reserved for control frames (PING/PONG)
- Payload: Variable length, type-specific
| Type | Name | Direction | Description |
|---|---|---|---|
| 0x01 | OPEN_STREAM | Edge → CLI | New incoming request. Payload: HTTP method, path, headers |
| 0x02 | STREAM_DATA | Both | Request/response body chunk |
| 0x03 | STREAM_END | Both | End of stream |
| 0x04 | STREAM_CANCEL | Both | Abort stream |
| 0x05 | RESPONSE_HEADERS | CLI → Edge | Response status + headers |
| 0x06 | WS_UPGRADE | Edge → CLI | Upgrade stream to WebSocket proxy mode |
| 0x07 | WS_DATA | Both | Raw WebSocket frame (in duplex mode) |
| 0x08 | WS_CLOSE | Both | WebSocket close |
| 0x09 | PING | Both | Keepalive |
| 0x0A | PONG | Both | Keepalive response |
| 0x0B | PAUSE | CLI → Edge | Pause tunnel; new requests return 503 |
| 0x0C | RESUME | CLI → Edge | Resume tunnel |
- Edge receives HTTP request → Sends
OPEN_STREAMwith streamId, method, path, headers - CLI receives OPEN_STREAM → Proxies request to localhost, gets response
- CLI sends RESPONSE_HEADERS → Status code, headers
- CLI sends STREAM_DATA (0+ chunks) → Response body
- CLI sends STREAM_END → Stream complete
Edge may send STREAM_CANCEL at any time. CLI must stop forwarding and send STREAM_END or STREAM_CANCEL.
When Edge detects Upgrade: websocket on incoming request:
- Edge sends
WS_UPGRADEinstead ofOPEN_STREAM - CLI opens WebSocket connection to localhost
- Stream switches to raw duplex:
WS_DATAandWS_CLOSEonly - No HTTP response headers—connection is upgraded
PING/PONG: StreamID = 0. Used for keepalive and connection health. No payload required.
- CLI sends PING every 25s.
- Gateway responds with PONG.
- If CLI does not receive PONG within 30s of sending PING, counts as 1 heartbeat failure.
- After 2 consecutive failures, CLI closes socket and triggers reconnect.
Before tunnel protocol:
- CLI calls Control Plane
POST /sessions - Receives:
sessionId,slug,publicUrl,edgeUrl,sessionToken,expiresAt - CLI connects WebSocket to
edgeUrlwithAuthorization: Bearer <sessionToken> - Edge validates token, binds
slug→ connection - Tunnel protocol begins
- Max concurrent streams per session: 100
- Max request body size: 10MB
- Idle timeout: 5 minutes (no PING/PONG or stream activity)
- Reconnect: CLI reconnects with same
sessionToken(no new session). Edge replaces slug→connection; old connection is closed.