authorgravatar for gbarros1095@gmail.comGuilherme Barros <gbarros1095@gmail.com> 2026-08-18 19:39:08+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-18 13:39:08-04:00
loga87f691bd40c9e3c87715e3ce99ab39a584bdd1e
tree0a728cd04f1da7e39e62e6b59132bbd781ca6802
parent1896f39a38f6fe980ea137fbc402dde8be17b83a
signature Signed by PGP key B5690EEEBB952194

fix(preview): open local environment ports on localhost (#7300)


2 files changed, 20 insertions(+), 4 deletions(-)

apps/web/src/browser/browserTargetResolver.test.ts+13-1
......@@ -173,7 +173,19 @@ describe("browser target resolver", () => {
173173 kind: "environment-port",
174174 port: 5173,
175175 }).resolvedUrl,
176 ).toBe("http://[::1]:5173/");
176 ).toBe("http://localhost:5173/");
177 });
178
179 it("maps local IPv4 environment ports onto localhost for dual-stack guests", async () => {
180 readPreparedConnection.mockReturnValue({ httpBaseUrl: "http://127.0.0.1:3773" });
181 const { resolveBrowserNavigationTarget } = await import("./browserTargetResolver");
182 expect(
183 resolveBrowserNavigationTarget(EnvironmentId.make("environment-1"), {
184 kind: "environment-port",
185 port: 5173,
186 path: "/app",
187 }).resolvedUrl,
188 ).toBe("http://localhost:5173/app");
177189 });
178190
179191 it("leaves malformed input for the normal navigation error path", async () => {
apps/web/src/browser/browserTargetResolver.ts+7-3
......@@ -178,9 +178,13 @@ const resolveEnvironmentPortTarget = (
178178 const protocol = target.protocol ?? "http";
179179 const path = target.path?.startsWith("/") ? target.path : `/${target.path ?? ""}`;
180180 const normalizedEnvironmentHost = environmentUrl.hostname.replace(/^\[|\]$/g, "");
181 const resolvedHost = normalizedEnvironmentHost.includes(":")
182 ? `[${normalizedEnvironmentHost}]`
183 : normalizedEnvironmentHost;
181 // Local loopback environments should advertise `localhost` so Chromium
182 // dual-stack lookup can reach a Vite server bound only to ::1 or 127.0.0.1.
183 const resolvedHost = isLocalLoopbackHost(normalizedEnvironmentHost)
184 ? "localhost"
185 : normalizedEnvironmentHost.includes(":")
186 ? `[${normalizedEnvironmentHost}]`
187 : normalizedEnvironmentHost;
184188 const resolved = sourceUrl
185189 ? new URL(sourceUrl)
186190 : new URL(path, `${protocol}://${resolvedHost}:${target.port}`);