Repository navigation
fix: cmux ssh browser loads pages and forwards localhost to the ssh host - #18956
Merged
Merged
Conversation
Contributor
|
All contributors have signed the CLA ✍️ ✅ |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 Walkthrough
|
Summary
In a
cmux sshworkspace (cmux-tui transport) the browser pane didn't work at all. Public pages stayed blank andlocalhost:3000never reached the ssh host's port 3000. Fixes #18249.Image drag into the browser looked broken for the same reason: no page ever loaded to receive the drop. It works now with no drop-path changes (recording below).
Two separate causes:
remoteProxyEndpoint, so every navigation queued inBrowserPanelwaiting for a proxy that never arrives. Public and private-network pages in an ssh workspace now load from this Mac. Loopback urls keep waiting until the owning ssh machine is registered, then resume on its route, so they never hit a same-port service on this Mac.PrivateAddressRouteSelectorcomparedlocalhostto the ssh machine's127.0.0.1as text, so it never matched. Even127.0.0.1went through the cmux-tui browser CONNECT proxy, which WebKit skips for loopback hosts. Loopback spellings (localhost,::1,0.0.0.0) now canonicalize to127.0.0.1before the selector. Ssh services use the existing.loopbackroute: onecmux-tui remote forward ssh://<dest> --port Nper port, and the browser loads the forward's local url. Retyping the remote address on a forwarded page also goes through the forward.This is a trimmed-down version of #18675 / #18382. It keeps their core routing (credit to @austinywang and @iamcobolt, co-authors on both commits) and leaves out the listener lease, the
--listen-fdrust change, the Mac-loopback content rules and the request-body preservation. Everything stays in the app target: no package or rust changes.After the correctness review, every loopback navigation in an ssh workspace goes through one gate: typed, history, restore, heal, and in-page links, redirects and script navigations. The only loopback url allowed straight through is the pane's own forward listener. A listener url opened in another tab maps back to its service. A forward whose child dies restarts, and the pane follows the new listener.
https://on an ssh host shows a clear "not supported yet" message instead of a spinner.Known gaps, for follow-ups:
localhosturls from a forwarded page still reach this Mac. fix: harden managed SSH browser routing #18675 has content rules for that.lvh.me) load locally.Testing
python3 scripts/verify-local.py --only swift-syntax --swift-changed: passed.python3 scripts/localization_catalog.py check: 0 parity errors.BrowserPanelInitialNavigationTests: public pages load in an ssh workspace, loopback stays off this Mac, loopback spellings route to the owning ssh machine.SSHTuiOpenTests: the forward child reports its port and stops, a child that exits early fails instead of hanging, ready-line parsing.cmux DEV ssh-browser, bf8d65e) dogfooded withcmux sshagainst a real Linux host. Port 3000 served "REMOTE" on the host and "MAC" on this Mac:example.comloads.localhost:3000shows the host's page, via127.0.0.1:<forward>.location.href = "http://localhost:3000/drop.html"inside the page is rerouted through the forward and still shows the host's page.image/png, the right size, with a thumbnail). The drop path itself is unchanged: drag only looked broken because the page never loaded.http://127.0.0.1:50604/) instead of the service the user opened.preferredURLStringForOmnibar()read WebKit's raw URL before the rewritten one, and the omnibar text, its edit buffer on click, reload and session history all share that read.restorableDisplayURLForCurrentErrorPage(liveURL:)now maps the live URL through the SSH display rewrite. Regression test:CloudPortRoutePlanTests.panelLiveURLReadersShowLogicalSSHService(red cc91b20, fix 1196eb9).pr-18956-ssh-browser-v30(1196eb9),cmux sshto a real macOS host runningpython3 -m http.server 5050. Opening the server's printedhttp://[::]:5050/link showshttp://localhost:5050/in the address bar, and the page comes from the host (its server log records the request). After a reload the bar still showshttp://localhost:5050/and the host logs a second request.Changelog
Fixed: Browser panes in
cmux sshworkspaces load web pages again, andlocalhostURLs open the SSH host's service instead of this Mac's, withlocalhost:<port>kept in the address bar.Proof
After-only screenshots above: the same port 3000 serves a red "MAC" page locally and a green "REMOTE" page on the ssh host.
Checklist
ssh.tui.browserForward.ended), translated in all 9 locales, catalog check passesNeed help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Note
Medium Risk
Changes core WebKit navigation and SSH port-forward lifecycle; mistakes could misroute loopback traffic or drop POST bodies on forward restart, though behavior is gated to SSH TUI workspaces with new tests.
Overview
Fixes browser panes in managed
cmux sshworkspaces so public pages load from this Mac instead of waiting forever on a workspace proxy that SSH never provides, while loopback URLs (localhost,127.0.0.1,::1, etc.) are routed to the SSH host via per-portcmux-tui remote forwardlisteners rather than this Mac’s same-port services.SSH forwarding & navigation:
SSHTuiLinkManagerowns loopback forward children (start/stop/restart on exit). SSH browser routes use.loopbackinCmuxTuiSurfaceProvider; HTTPS on SSH hosts is blocked with a localized message.CloudBrowserAccessStatenow replays full **URLRequest**s (method/headers/body) when forwards restart, canonicalizes loopback identity for the address bar, and tracks retired listener ports.BrowserPanelandBrowserNavigationDelegatefunnel typed/history/restore/link/redirect loopback traffic through one SSH gate; in-page redirects to an existing forward rewrite to the live listener with the correct Host header.Related fixes: Cloud workspace creation focus respects admission revision so a delayed provider doesn’t steal focus; fresh SSH opens can skip an initial graph refresh; mirror detach no longer auto-spawns a duplicate terminal; new localized strings for forward failure and HTTPS unsupported.
Tests cover SSH routing, forward process lifecycle, request replay, and display URL behavior.
Reviewed by Cursor Bugbot for commit 7f19f19. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Fixes browser panes in managed
cmux sshworkspaces: public pages load from this Mac, while loopback URLs reach services on the SSH host through per-portcmux-tui remote forwardlisteners.localhost,::1,0.0.0.0,127.0.0.1) canonicalize to a stablelocalhost:<port>identity and route typed URLs, history, restores, links, redirects, and scripts through one SSH gate; a restarting forward keeps the page loaded through the new listener, preserves the request's method, headers, and body, and keeps the service URL in the omnibar, edit buffer, reload, and session history instead of the ephemeral listener port.Known limitations
localhostlinks inside forwarded pages aren't rewritten.Written for commit a1be35a. Summary will update on new commits.
Summary by CodeRabbit
http://address when available.