🤖 feat: proxy localhost URLs through Coder wildcard DNS in browser mode#2797
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e998de11af
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Re: the P1 concern about I investigated both upstream repos (coder/coder and coder/code-server) to verify whether path-based proxy templates are a real production scenario: Coder platform: code-server: While it does support path-based templates internally ( Conclusion: Since Coder never produces path-based templates for |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e998de11af
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Both prior Codex review comments were investigated by cloning the upstream coder/coder and coder/code-server repos. Both were false alarms: P1: "Preserve proxy template path when rewriting localhost URLs" Why this is wrong:
P2: "Pass hostname, not host, into localhost proxy normalization" Why this is wrong:
The one valid observation was an internal inconsistency: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 279f21a3db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review All review threads across all rounds are resolved. Summary: Round 1:
Round 2:
|
|
Codex Review: Didn't find any major issues. Keep it up! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79d52244c7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review All review threads across all three rounds are resolved. Full accounting: Round 1 (2 threads):
Round 2 (2 threads):
Round 3 (1 thread):
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79d52244c7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Changes since last review:
|
Adds Coder-style localhost link proxying so clicked localhost URLs
open through the workspace proxy (VSCODE_PROXY_URI / MUX_PROXY_URI).
- Shared normalizer: src/common/utils/localhostProxyUrl.ts
Rewrites loopback HTTP(S) URLs using {{port}}/{{host}} templates.
Preserves path/query/hash. Falls back to original on any failure.
- Electron (#1): main window + terminal pop-out windows normalize
URLs before shell.openExternal via setWindowOpenHandler and
will-navigate handlers.
- Terminal env (#2): PTY sessions inherit VSCODE_PROXY_URI and
MUX_PROXY_URI (with override precedence) for CLI tool parity.
- Browser mode (#3): server injects __MUX_PROXY_URI_TEMPLATE__ into
SPA shell. Both entrypoints install a window.open wrapper that
normalizes loopback URLs.
- Markdown links (#4): chat anchor renderer normalizes href via the
same shared policy.
2ed76b9 to
491c01c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 491c01c9e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review Changes since last review:
|
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
When Mux runs inside a Coder workspace, clicking a
localhost:PORTlink anywhere in the app now transparently opens through the Coder wildcard proxy URL instead. Works zero-config in browser mode by deriving the proxy template from the current hostname (e.g.5173--dev--ws--user--apps.example.com→{{port}}--dev--ws--user--apps.example.com), and also supports explicitVSCODE_PROXY_URI/MUX_PROXY_URIenv vars for Electron mode.Closes #2376
Background
Coder's web terminal and code-server both rewrite localhost URLs to proxy URLs so that clicking
http://localhost:3000in a remote workspace opens the correct externally-reachable URL. Mux lacked this — users in Coder environments had to manually construct proxy URLs.Key insight from upstream:
VSCODE_PROXY_URIis only injected by Coder into VS Code extension host processes, not into plain SSH shells. So env-var-only detection is insufficient for browser mode. code-server solves this by deriving the template fromwindow.location; Coder's web terminal gets it from the/api/v2/regionsAPI. We take the simpler code-server-like approach: if the browser hostname looks like a Coder port-forward URL (<port>--<segments>.<domain>), derive the template by replacing the port prefix with{{port}}.Implementation
Architecture: one shared pure normalizer + thin adapters at each navigation boundary + browser-side auto-detection.
src/common/utils/localhostProxyUrl.ts{{port}}/{{host}}template. Supports both subdomain-based and path-based proxy templates (preserves template path prefix). Preserves path/query/hash. Falls back to original URL on any failure.src/browser/utils/browserLocalhostProxyTemplate.tswindow.location.hostnamewhen no injected template exists. Detects Coder-style<port>--<suffix>.<domain>hostnames and synthesizes{{port}}--<suffix>.<domain>.src/desktop/main.ts,src/desktop/terminalWindowManager.tssetWindowOpenHandler+will-navigatepass URLs through normalizer beforeshell.openExternal().src/node/services/terminalService.tsVSCODE_PROXY_URIandMUX_PROXY_URIso CLI tools can use them.src/node/orpc/server.ts,src/browser/utils/windowOpenLocalhostProxy.tswindow.__MUX_PROXY_URI_TEMPLATE__into SPA shell (static middleware skipsindex.htmlso the SPA fallback is the single source of truth for HTML delivery).window.openwrapper normalizes loopback URLs.src/browser/features/Messages/MarkdownComponents.tsxhrefvia the same shared policy.Template resolution order (browser mode):
window.__MUX_PROXY_URI_TEMPLATE__(fromMUX_PROXY_URI>VSCODE_PROXY_URIenv vars)window.location.hostnameif it matches Coder's<port>--...patternTemplate resolution order (Electron):
MUX_PROXY_URI>VSCODE_PROXY_URI> no rewrite.Validation
make static-checkpassesRisks
Low. All rewrite paths fall back to the original URL on any failure. The Coder hostname auto-detection is conservative — it only activates when the first DNS label is
<digits>--<at-least-one-segment>, which is specific to Coder's wildcard proxy format.Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:xhigh