You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
viteDevframeHub only shares Vite's server for the WebSocket upgrade when server.httpServer instanceof http.Server. With server.https (or @vitejs/plugin-basic-ssl), Vite creates an Http2SecureServer with allowHTTP1, or an https.Server when server.proxy is set. Neither passes the check, so the plugin falls back to a plain ws side-car on its own port.
__connection.json then advertises { port: 9777, path: '__ws' }. On an https page the client resolves that to wss://localhost:9777/__ws, but the side-car does not speak TLS, so the handshake fails. The client picks the WebSocket whenever one is advertised, so it never falls back to SSE and the hub stays stuck connecting.
Both server types emit upgrade for HTTP/1.1 requests (Vite's own HMR socket depends on this), and the ws transport already accepts an https server. This change passes server.httpServer through whenever it exists, like devframeViteBridge in single.ts already does. The side-car is still used for a pinned port and for middleware mode (no httpServer).
angular-devtools had the same instanceof check in its own Vite plugin and fixed it by attaching handleUpgrade to the dev server's upgrade event, which is what this change does for the hub.
Reproduction
Add viteDevframeHub() to a Vite app and enable server.https (for example with @vitejs/plugin-basic-ssl).
Open the app over https.
__devframes/__connection.json advertises a side-car port, and the socket to wss://localhost:<port>/__ws fails. wss://localhost:<vite port>/__devframes/__ws returns 404 because nothing listens for the upgrade there.
How I tested
New packages/vite/test/hub.test.ts: a fake Vite server whose httpServer is http2.createSecureServer({ allowHTTP1: true }). It checks that __connection.json advertises { path: '/__devframes/__ws' } and that the hub attached an upgrade listener. Before the fix it fails with expected { port: 9777, path: '__ws' } to deeply equal { path: '/__devframes/__ws' }.
By hand, with a self-signed cert on a real Http2SecureServer and the built plugin: a ws client to wss://127.0.0.1:<port>/__devframes/__ws opens after the fix and gets Unexpected server response: 404 before it.
vitest run --project @devframes/vite (11 passed), eslint on the changed files, and tsc --noEmit for the package.
Follow-up from review
instance-shell.ts now advertises wss:// and an https:// origin when the shared server is a TLS server, so remote docks on an https host get a secure endpoint (tested in initiate.test.ts).
hub.test.ts now does a real wss:// handshake against an Http2SecureServer with a throwaway self-signed cert.
Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
🪧 More tips
Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
Untick Architecture lens or Data flow lens under View to hide a diagram, or tick Expand every detail to open every section. The comment redraws in a few seconds
Click the link under each diagram to open it on a canvas you can zoom, pan and step through
The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
Push a commit and the drawing stays, with a note that it is out of date. Tick Redraw in the note to draw the new head
Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Remove ad-hoc warning for conditionally skipped suites
packages/vite/test/hub.test.ts:31
This raw Node-side warning violates the repository's coded-diagnostics rule in .agents/08-diagnostics.md. Vitest already reports the conditionally skipped suite, so remove this ad-hoc warning rather than adding a diagnostic solely for the test environment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
viteDevframeHubonly shares Vite's server for the WebSocket upgrade whenserver.httpServer instanceof http.Server. Withserver.https(or@vitejs/plugin-basic-ssl), Vite creates anHttp2SecureServerwithallowHTTP1, or anhttps.Serverwhenserver.proxyis set. Neither passes the check, so the plugin falls back to a plainwsside-car on its own port.__connection.jsonthen advertises{ port: 9777, path: '__ws' }. On an https page the client resolves that towss://localhost:9777/__ws, but the side-car does not speak TLS, so the handshake fails. The client picks the WebSocket whenever one is advertised, so it never falls back to SSE and the hub stays stuck connecting.Both server types emit
upgradefor HTTP/1.1 requests (Vite's own HMR socket depends on this), and the ws transport already accepts an https server. This change passesserver.httpServerthrough whenever it exists, likedevframeViteBridgeinsingle.tsalready does. The side-car is still used for a pinnedportand for middleware mode (nohttpServer).angular-devtools had the same
instanceofcheck in its own Vite plugin and fixed it by attachinghandleUpgradeto the dev server'supgradeevent, which is what this change does for the hub.Reproduction
viteDevframeHub()to a Vite app and enableserver.https(for example with@vitejs/plugin-basic-ssl).__devframes/__connection.jsonadvertises a side-car port, and the socket towss://localhost:<port>/__wsfails.wss://localhost:<vite port>/__devframes/__wsreturns 404 because nothing listens for the upgrade there.How I tested
packages/vite/test/hub.test.ts: a fake Vite server whosehttpServerishttp2.createSecureServer({ allowHTTP1: true }). It checks that__connection.jsonadvertises{ path: '/__devframes/__ws' }and that the hub attached anupgradelistener. Before the fix it fails withexpected { port: 9777, path: '__ws' } to deeply equal { path: '/__devframes/__ws' }.Http2SecureServerand the built plugin: awsclient towss://127.0.0.1:<port>/__devframes/__wsopens after the fix and getsUnexpected server response: 404before it.vitest run --project @devframes/vite(11 passed), eslint on the changed files, andtsc --noEmitfor the package.Follow-up from review
instance-shell.tsnow advertiseswss://and anhttps://origin when the shared server is a TLS server, so remote docks on an https host get a secure endpoint (tested ininitiate.test.ts).hub.test.tsnow does a realwss://handshake against anHttp2SecureServerwith a throwaway self-signed cert.