fix(browser): preserve explicit cdpPort when cdpUrl omits port

This commit is contained in:
clawsweeper
2026-05-18 18:10:12 +00:00
parent 989fc9f5b4
commit 070c31cdcf
2 changed files with 9 additions and 15 deletions

View File

@@ -28,17 +28,14 @@ export { isLoopbackHost };
function hasRawExplicitPort(raw: string): boolean {
// Strip scheme (e.g. "http://") and take only the authority portion
// (everything before the first /, ?, or #).
const authority =
raw
.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "")
.split(/[/?#]/, 1)[0] ?? "";
const authority = raw.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").split(/[/?#]/, 1)[0] ?? "";
// Strip userinfo (user:pass@) the colon there is NOT a port separator.
// Strip userinfo (user:pass@); the colon there is not a port separator.
const hostPort = authority.includes("@")
? authority.slice(authority.lastIndexOf("@") + 1)
: authority;
// IPv6: [::1]:9222 port after closing bracket
// IPv6: [::1]:9222 has a port after the closing bracket.
if (hostPort.startsWith("[")) {
return /^\[[^\]]+\]:\d+$/.test(hostPort);
}
@@ -88,7 +85,7 @@ export function parseBrowserHttpUrl(raw: string, label: string) {
const atIdx = rest.indexOf("@");
const hostStart = atIdx >= 0 ? atIdx + 1 : 0;
const hostPart = rest.slice(hostStart);
// Find end of host: IPv6 brackets or first : / /
// Find the end of the host: IPv6 brackets, a path slash, or a port colon.
const hostLen = hostPart.startsWith("[")
? hostPart.indexOf("]") + 1
: (() => {
@@ -96,8 +93,7 @@ export function parseBrowserHttpUrl(raw: string, label: string) {
return idx < 0 ? hostPart.length : idx;
})();
const insertAt = hostStart + hostLen;
normalizedWithPort =
proto + rest.slice(0, insertAt) + ":" + port + rest.slice(insertAt);
normalizedWithPort = proto + rest.slice(0, insertAt) + ":" + port + rest.slice(insertAt);
} else {
normalizedWithPort = normalized;
}

View File

@@ -621,9 +621,7 @@ describe("browser config", () => {
const websocket = resolveProfile(resolved, "websocket");
expect(websocket?.cdpPort).toBe(443);
expect(websocket?.cdpUrl).toBe(
"wss://remote-browser.example.com:443/json/version?token=abc",
);
expect(websocket?.cdpUrl).toBe("wss://remote-browser.example.com:443/json/version?token=abc");
const ipv6 = resolveProfile(resolved, "ipv6");
expect(ipv6?.cdpPort).toBe(80);
@@ -716,9 +714,7 @@ describe("browser config", () => {
},
},
});
expect(() => resolveProfile(resolved, "bad")).toThrow(
'must define cdpPort or cdpUrl',
);
expect(() => resolveProfile(resolved, "bad")).toThrow("must define cdpPort or cdpUrl");
});
it("stale WS devtools URL + cdpPort drops path and uses cdpPort", () => {
@@ -735,6 +731,8 @@ describe("browser config", () => {
const profile = resolveProfile(resolved, "chrome-cdp");
expect(profile?.cdpUrl).toBe("http://127.0.0.1:9222");
expect(profile?.cdpPort).toBe(9222);
expect(profile?.cdpIsLoopback).toBe(true);
expect(profile?.attachOnly).toBe(true);
});
it("IPv6 URL without port defers to cdpPort", () => {