From 48a111c3311e1c76eb04ef0e1b35edfdbf2c6af1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:01:57 +0000 Subject: [PATCH 1/8] Initial plan From f0dd279e4ed3f070b7188ab0a54c25a21348c79b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:04:48 +0000 Subject: [PATCH 2/8] Read IP address from server.address() and handle IPv6 formatting Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- .../src/HttpServer.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 8f57bff9e0..4e4b3e5dae 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -17,7 +17,7 @@ const LOCALHOST_IP: string = '127.0.0.1'; export class HttpServer { private readonly _server: http.Server; private readonly _wsServer: WebSocketServer; // local proxy websocket server accepting browser clients - private _listeningPort: number | undefined; + private _listeningAddress: string | undefined; private _logger: ITerminal; public constructor(logger: ITerminal) { @@ -38,21 +38,25 @@ export class HttpServer { public listen(): Promise { return new Promise((resolve) => { this._server.listen(0, LOCALHOST_IP, () => { - this._listeningPort = (this._server.address() as AddressInfo).port; + const addressInfo = this._server.address() as AddressInfo; + // Handle IPv6 addresses with proper formatting + const address: string = + addressInfo.family === 'IPv6' + ? `[${addressInfo.address}]:${addressInfo.port}` + : `${addressInfo.address}:${addressInfo.port}`; + this._listeningAddress = address; // This MUST be printed to terminal so VS Code can auto-port forward - this._logger.writeLine( - `Local proxy HttpServer listening at ws://${LOCALHOST_IP}:${this._listeningPort}` - ); + this._logger.writeLine(`Local proxy HttpServer listening at ws://${address}`); resolve(); }); }); } public get endpoint(): string { - if (this._listeningPort === undefined) { + if (this._listeningAddress === undefined) { throw new Error('HttpServer not listening yet'); } - return `ws://${LOCALHOST_IP}:${this._listeningPort}`; + return `ws://${this._listeningAddress}`; } public get wsServer(): WebSocketServer { From bd3a2e04f046d6d620d2eb42332a5ca16f53c973 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:06:03 +0000 Subject: [PATCH 3/8] Use 'localhost' instead of hardcoded IPv4 to allow system to choose IPv4 or IPv6 Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- apps/playwright-browser-tunnel/src/HttpServer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 4e4b3e5dae..f8e97217ff 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -7,7 +7,7 @@ import { WebSocketServer, type WebSocket, type AddressInfo } from 'ws'; import type { ITerminal } from '@rushstack/terminal'; -const LOCALHOST_IP: string = '127.0.0.1'; +const LOCALHOST: string = 'localhost'; /** * This HttpServer is used for the localProxyWs WebSocketServer. @@ -37,7 +37,7 @@ export class HttpServer { public listen(): Promise { return new Promise((resolve) => { - this._server.listen(0, LOCALHOST_IP, () => { + this._server.listen(0, LOCALHOST, () => { const addressInfo = this._server.address() as AddressInfo; // Handle IPv6 addresses with proper formatting const address: string = From 2a94ffb163d89fd29de824a5258b237197e801e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:06:38 +0000 Subject: [PATCH 4/8] Rename address variable to formattedAddress for clarity Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- apps/playwright-browser-tunnel/src/HttpServer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index f8e97217ff..98107f49e5 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -40,13 +40,13 @@ export class HttpServer { this._server.listen(0, LOCALHOST, () => { const addressInfo = this._server.address() as AddressInfo; // Handle IPv6 addresses with proper formatting - const address: string = + const formattedAddress: string = addressInfo.family === 'IPv6' ? `[${addressInfo.address}]:${addressInfo.port}` : `${addressInfo.address}:${addressInfo.port}`; - this._listeningAddress = address; + this._listeningAddress = formattedAddress; // This MUST be printed to terminal so VS Code can auto-port forward - this._logger.writeLine(`Local proxy HttpServer listening at ws://${address}`); + this._logger.writeLine(`Local proxy HttpServer listening at ws://${formattedAddress}`); resolve(); }); }); From f16cb6574871a5105632a5549cfbec37b03fca25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:09:10 +0000 Subject: [PATCH 5/8] Add null check and handle both string and number IPv6 family values Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- apps/playwright-browser-tunnel/src/HttpServer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 98107f49e5..4267df0a88 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -39,9 +39,13 @@ export class HttpServer { return new Promise((resolve) => { this._server.listen(0, LOCALHOST, () => { const addressInfo = this._server.address() as AddressInfo; + if (!addressInfo) { + throw new Error('Failed to get server address'); + } // Handle IPv6 addresses with proper formatting + // AddressInfo.family can be 'IPv6' (string) or 6 (number) const formattedAddress: string = - addressInfo.family === 'IPv6' + addressInfo.family === 'IPv6' || addressInfo.family === 6 ? `[${addressInfo.address}]:${addressInfo.port}` : `${addressInfo.address}:${addressInfo.port}`; this._listeningAddress = formattedAddress; From eb3f7f862218b65fcd4d485c8e887c02261170c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:10:17 +0000 Subject: [PATCH 6/8] Import AddressInfo from node:net and fix IPv6 family check Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- apps/playwright-browser-tunnel/src/HttpServer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 4267df0a88..2fd1d54a07 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -2,8 +2,9 @@ // See LICENSE in the project root for license information. import http from 'node:http'; +import type { AddressInfo } from 'node:net'; -import { WebSocketServer, type WebSocket, type AddressInfo } from 'ws'; +import { WebSocketServer, type WebSocket } from 'ws'; import type { ITerminal } from '@rushstack/terminal'; @@ -43,9 +44,8 @@ export class HttpServer { throw new Error('Failed to get server address'); } // Handle IPv6 addresses with proper formatting - // AddressInfo.family can be 'IPv6' (string) or 6 (number) const formattedAddress: string = - addressInfo.family === 'IPv6' || addressInfo.family === 6 + addressInfo.family === 'IPv6' ? `[${addressInfo.address}]:${addressInfo.port}` : `${addressInfo.address}:${addressInfo.port}`; this._listeningAddress = formattedAddress; From d092d430e5e31b0f00c1fb48ef77c2a0b25e56bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:11:17 +0000 Subject: [PATCH 7/8] Improve type safety for server.address() return value Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- apps/playwright-browser-tunnel/src/HttpServer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 2fd1d54a07..5a25e360b8 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -39,8 +39,8 @@ export class HttpServer { public listen(): Promise { return new Promise((resolve) => { this._server.listen(0, LOCALHOST, () => { - const addressInfo = this._server.address() as AddressInfo; - if (!addressInfo) { + const addressInfo = this._server.address(); + if (!addressInfo || typeof addressInfo === 'string') { throw new Error('Failed to get server address'); } // Handle IPv6 addresses with proper formatting From 6e1bee40743cbc89ab410508a6912ecd6314e759 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 00:12:04 +0000 Subject: [PATCH 8/8] Extract formatAddress helper and improve error messages Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- .../src/HttpServer.ts | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/playwright-browser-tunnel/src/HttpServer.ts b/apps/playwright-browser-tunnel/src/HttpServer.ts index 5a25e360b8..c87db4dd1a 100644 --- a/apps/playwright-browser-tunnel/src/HttpServer.ts +++ b/apps/playwright-browser-tunnel/src/HttpServer.ts @@ -10,6 +10,17 @@ import type { ITerminal } from '@rushstack/terminal'; const LOCALHOST: string = 'localhost'; +/** + * Formats an address info object into a WebSocket-compatible address string. + * IPv6 addresses are formatted with brackets: [address]:port + * IPv4 addresses are formatted as: address:port + */ +function formatAddress(addressInfo: AddressInfo): string { + return addressInfo.family === 'IPv6' + ? `[${addressInfo.address}]:${addressInfo.port}` + : `${addressInfo.address}:${addressInfo.port}`; +} + /** * This HttpServer is used for the localProxyWs WebSocketServer. * The purpose is to parse the query params and path for the websocket url to get the @@ -38,16 +49,19 @@ export class HttpServer { public listen(): Promise { return new Promise((resolve) => { + // Bind to 'localhost' which resolves to IPv4 (127.0.0.1) or IPv6 (::1) + // depending on system configuration and DNS resolution this._server.listen(0, LOCALHOST, () => { const addressInfo = this._server.address(); - if (!addressInfo || typeof addressInfo === 'string') { - throw new Error('Failed to get server address'); + if (!addressInfo) { + throw new Error('Server address is null - server may not be bound properly'); + } + if (typeof addressInfo === 'string') { + throw new Error( + `Server address is a pipe/socket path (${addressInfo}), expected an IP address` + ); } - // Handle IPv6 addresses with proper formatting - const formattedAddress: string = - addressInfo.family === 'IPv6' - ? `[${addressInfo.address}]:${addressInfo.port}` - : `${addressInfo.address}:${addressInfo.port}`; + const formattedAddress: string = formatAddress(addressInfo); this._listeningAddress = formattedAddress; // This MUST be printed to terminal so VS Code can auto-port forward this._logger.writeLine(`Local proxy HttpServer listening at ws://${formattedAddress}`);