WebSocket upgrade not tunneled — clients reconnect-loop through proxy #29
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_proxy#29
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
proxy.rs::proxy_handlerends with a single line forwarding every request viacrate::domain::forward_to_upstream, which is a plain HTTP request/response forwarder — noUpgrade: websocketdetection, nohyper::upgrade::on(&mut req), no bidirectional splice after101 Switching Protocols.Result: when a browser opens a WebSocket through the proxy:
Connection: upgrade+Upgrade: websocket101 Switching Protocols(its ownproxy_ws_tunnelhandles the UDS side correctly)ws.onclosefires, schedules reconnect (1s backoff)In collab specifically this manifests as a flood of
ws/user/{id}requests in the network tab, each followed immediately by a close, plus a flood ofmessage.list/mention.list/read.markcalls (the catch-up cycle fires on every reconnect).Severity
Anything WebSocket-shaped behind hero_proxy is broken:
/hero_collab/ui/ws/user/{id})/hero_collab/ui/ws/canvas/{id})/hero_proc/ui/api/services/{name}/pty)Verification
Same WS upgrade headers, two paths — currently produce different behaviour:
After the fix in
feat/ws-upgrade-tunnel, both responses include identicalSec-WebSocket-Acceptand the connection survives.Workaround
Hit hero_router directly on
:9988(itsproxy_ws_tunnelhandles UDS WS correctly). Not viable for any deployment that exposes only the proxy.Fix shape
Connection: upgrade+Upgrade: websocket(is_ws_upgrade).proxy_ws_tunnel:hyper::upgrade::on(&mut req)for the client side before consuming the request.router_url).with_upgrades()enabled.Empty<Bytes>.101 Switching Protocols; bail with the upstream's status otherwise.tokio::io::copy_bidirectional.forward_to_upstreampath.Out of scope (separate follow-up)
dispatch_domain_route(host-matched path with bearer/OAuth/signature/IP auth) still uses regular HTTP forwarding. No domain route fronts a WebSocket service today; can be addressed when one does. UDS-targeted variant of the tunnel needed for that path.vary/ CORS headers (both router and proxy add them). Functionally harmless; ~5 LOC fix.PR
Fix in
feat/ws-upgrade-tunnel. Pattern mirrors hero_router'sproxy_ws_tunnelbut TCP-targeted instead of UDS-targeted. ~210 LOC added (helpers + branch). No removals.