Skip to content

feat(devframe): proxy-flexible, route-bound WebSocket endpoint#6

Closed
antfubot wants to merge 1 commit into
mainfrom
tame-books-hear
Closed

feat(devframe): proxy-flexible, route-bound WebSocket endpoint#6
antfubot wants to merge 1 commit into
mainfrom
tame-books-hear

Conversation

@antfubot

Copy link
Copy Markdown
Owner

Why

The dev server already shared one port for HTTP and the RPC WebSocket, but the WS server claimed every upgrade on that port and the SPA discovered it via a server-baked host/port. That breaks two scenarios:

  1. Mixed servers — mounting the socket onto a host server (e.g. a Vite dev server with its own HMR socket and routes) was unsafe, since devframe would intercept unrelated upgrades.
  2. Reverse proxies — when the page is served through a proxy that rewrites the domain, port, or subpath, a host/port baked into __connection.json is no longer reachable.

What

Bind the WebSocket to a dedicated route, shared on the web server's port by default

  • New DEVFRAME_WS_ROUTE (__devframe_ws) constant, mounted next to __connection.json.
  • attachWsRpcTransport gains server, path, and destroyUnmatched options. With a path it routes only the matching upgrade pathname and leaves non-matching upgrades for other listeners (so a host's HMR socket keeps working); it returns a detach(). The server option mounts onto an existing HTTP server, sharing its port.
  • startHttpAndWs gains path and server options — pass an external server to embed the socket inside a host server (devframe never closes a server it doesn't own); when devframe owns the server, off-route upgrades are rejected promptly.

Proxy-flexible __connection.json

  • ConnectionMeta.websocket now accepts number | string | { path?, port?, host? }.
  • The client (resolveWsUrl) follows the page's own origin for the relative/path form — resolving against where __connection.json loaded and only swapping httpws / httpswss — so the connection survives a proxy that changes host/port/subpath. Explicit port/host or a full ws(s):// string opt into a fixed cross-origin endpoint (e.g. a side-car).
  • The standalone dev server now advertises { websocket: { path: "__devframe_ws" } }; the Vite side-car carries its own { port, path } since it is genuinely cross-port.

Backward compatible: with no path, the transport keeps its legacy all-upgrades behavior, and numeric/string websocket descriptors still resolve as before.

Tests

  • resolveWsUrl proxy / cross-origin resolution matrix.
  • Shared-server coexistence with a simulated HMR socket on a sibling route.
  • End-to-end route binding for the dev server (on-route connects, off-route rejected).
  • Full suite green (513 passed); API snapshots updated for the new exports.

This PR was created with the help of an agent.

@antfubot

Copy link
Copy Markdown
Owner Author

Superseded by devframes#51 (opened against the upstream repo).

@antfubot antfubot closed this Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant