-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
In many corporate/enterprise network environments, HTTP proxies or firewalls block WebSocket (wss://) connections. This makes CloudCLI completely unusable for both the Chat interface and the Shell terminal, as both rely exclusively on WebSocket transport.
Affected scenarios:
- Corporate HTTP proxies that only allow standard HTTP/HTTPS traffic
- Firewalls with deep packet inspection that strip
Upgrade: websocketheaders - Restrictive network policies that whitelist only ports 80/443 with HTTP-only protocols
- SSE (Server-Sent Events) is also blocked in some environments
Proposed Solution
Implement an automatic HTTP Long Polling fallback that transparently substitutes WebSocket when connections fail. The design should:
1. Auto-detection & transparent fallback
- Track WebSocket connection failures (e.g., after 3 consecutive failures)
- Automatically switch to HTTP polling mode without user intervention
- No degradation for users with working WebSocket connections
2. Chat polling transport (/ws replacement)
POST /api/poll/connect— register a polling connectionGET /api/poll/messages— drain queued messages (with aggressive cache-busting headers)POST /api/poll/send— send commands (claude-command, abort-session, etc.)POST /api/poll/disconnect— cleanup- Adaptive polling interval: ~100ms during activity, ~500ms when idle
- 10ms yield between message dispatches to prevent React setState batching issues
3. Shell polling transport (/shell replacement)
POST /api/poll/shell/connect— register shell polling + spawn PTY viahandleShellConnectionGET /api/poll/shell/output— drain PTY output queuePOST /api/poll/shell/send— forward init/input/resize to PTYPOST /api/poll/shell/disconnect— cleanup- Faster polling interval (~50ms active / ~200ms idle) for interactive terminal feel
- Server-side
FakeShellWs(EventEmitter) that mimics WebSocket API forhandleShellConnectioncompatibility
4. Frontend monkey-patch approach
- Intercept
new WebSocket(url)calls for/ws?token=and/shell?token=URLs - Replace with
PollingWebSocket/PollingShellWebSocketclasses that usefetch()internally - Maintain full WebSocket API compatibility (readyState, onopen, onmessage, onclose, send, close, addEventListener)
Implementation Notes
I have a working proof-of-concept deployed in a production environment behind an Nginx reverse proxy with SSL. Key learnings:
- Cache-busting is critical — Browser/proxy caching of poll responses causes stale data. Need
Cache-Control: no-store, uniqueETag, and_t=Date.now()query params. - Auth must use headers, not query params — Passing JWT tokens as URL query parameters causes
jwt malformederrors in some proxy configurations. UseAuthorization: Bearerheader instead. - React setState batching — Dispatching multiple
onmessageevents synchronously causes React to only render the last message. A smallawait setTimeout(10ms)between dispatches fixes this. - Service Worker interference — SW caching of
index.htmlprevents users from getting updated polling code. Cache version bumping is needed.
Ideal Implementation Path
Rather than the monkey-patch approach (which works but is fragile), the proper implementation would be:
- Add polling transport as a first-class option in the React source code (e.g.,
usePollingWebSockethook) - Server-side polling endpoints as a separate Express router module
- Environment variable to force polling mode:
FORCE_POLLING=true - Auto-detection built into the WebSocket connection hook with configurable threshold
Environment
- CloudCLI version: 1.25.2 (npm
@siteboon/claude-code-ui) - Deployment: Linux server behind Nginx reverse proxy with SSL
- Corporate network: HTTP proxy blocking WebSocket and SSE
Submitted by @ShijunDeng — happy to contribute a PR if the maintainers are interested in this direction.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request