diff --git a/docs/src/api/class-browsertype.md b/docs/src/api/class-browsertype.md index b09409a780..368f697ed3 100644 --- a/docs/src/api/class-browsertype.md +++ b/docs/src/api/class-browsertype.md @@ -124,6 +124,22 @@ Logger sink for Playwright logging. Optional. Maximum time in milliseconds to wait for the connection to be established. Defaults to `0` (no timeout). +### option: BrowserType.connect.exposeNetwork +* since: v1.37 +- `exposeNetwork` <[string]> + +This option exposes network available on the connecting client to the browser being connected to. Consists of a list of rules separated by comma. + +Available rules: +1. Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`. +1. IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`. +1. `` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. + +Some common examples: +1. `"*"` to expose all network. +1. `""` to expose localhost network. +1. `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and localhost. + ## async method: BrowserType.connectOverCDP * since: v1.9 - returns: <[Browser]> diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index 90028a2aeb..23e7a93ff6 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -97,7 +97,7 @@ export class BrowserType extends ChannelOwner imple 'x-playwright-launch-options': jsonStringifyForceASCII({ ...this._defaultLaunchOptions, ...launchOptions }), ...connectOptions.headers, }, - _exposeNetwork: connectOptions._exposeNetwork, + exposeNetwork: connectOptions.exposeNetwork ?? connectOptions._exposeNetwork, slowMo: connectOptions.slowMo, timeout: connectOptions.timeout ?? 3 * 60 * 1000, // 3 minutes }); @@ -149,7 +149,7 @@ export class BrowserType extends ChannelOwner imple const connectParams: channels.LocalUtilsConnectParams = { wsEndpoint: params.wsEndpoint, headers, - exposeNetwork: params._exposeNetwork, + exposeNetwork: params.exposeNetwork ?? params._exposeNetwork, slowMo: params.slowMo, timeout: params.timeout, }; diff --git a/packages/playwright-core/src/client/types.ts b/packages/playwright-core/src/client/types.ts index e9fdb61c09..9f8845aded 100644 --- a/packages/playwright-core/src/client/types.ts +++ b/packages/playwright-core/src/client/types.ts @@ -87,6 +87,7 @@ export type LaunchPersistentContextOptions = Omit` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. + * + * Some common examples: + * 1. `"*"` to expose all network. + * 1. `""` to expose localhost network. + * 1. `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and + * localhost. + */ + exposeNetwork?: string; + /** * Additional HTTP headers to be sent with web socket connect request. Optional. */ diff --git a/packages/playwright-test/src/index.ts b/packages/playwright-test/src/index.ts index a5b56be61e..7c816225e7 100644 --- a/packages/playwright-test/src/index.ts +++ b/packages/playwright-test/src/index.ts @@ -514,7 +514,7 @@ function connectOptionsFromEnv() { return { wsEndpoint, headers, - _exposeNetwork: process.env.PW_TEST_CONNECT_EXPOSE_NETWORK, + exposeNetwork: process.env.PW_TEST_CONNECT_EXPOSE_NETWORK, }; } diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index b6ba325987..7eb840b2d3 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -3392,6 +3392,22 @@ type ConnectOptions = { */ headers?: { [key: string]: string; }; + /** + * This option exposes network available on the connecting client to the browser being connected to. + * Consists of a list of rules separated by comma. + * + * Available rules: + * - Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`. + * - IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`. + * - `` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. + + * Some common examples: + * - `"*"` to expose all network. + * - `""` to expose localhost network. + * - `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and localhost. + */ + exposeNetwork?: string; + /** * Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout. */ diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index b036c0e2f0..ff85ace7c6 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -736,7 +736,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { res.end('original-target'); }); const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: '*' } as any); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: '*' }); const page = await browser.newPage(); await page.goto(server.PREFIX + '/foo.html'); expect(await page.content()).toContain('original-target'); @@ -770,7 +770,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); const examplePort = 20_000 + testInfo.workerIndex * 3; const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: '*' } as any, ipV6ServerPort); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: '*' }, ipV6ServerPort); const page = await browser.newPage(); await page.goto(`http://[::1]:${examplePort}/foo.html`); expect(await page.content()).toContain('from-ipv6-server'); @@ -790,7 +790,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); const examplePort = 20_000 + workerInfo.workerIndex * 3; const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: '*' } as any, dummyServerPort); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: '*' }, dummyServerPort); const page = await browser.newPage(); const response = await page.request.get(`http://127.0.0.1:${examplePort}/foo.html`); expect(response.status()).toBe(200); @@ -806,7 +806,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); const examplePort = 20_000 + workerInfo.workerIndex * 3; const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: '*' } as any, dummyServerPort); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: '*' }, dummyServerPort); const page = await browser.newPage(); await page.goto(`http://local.playwright:${examplePort}/foo.html`); expect(await page.content()).toContain('from-dummy-server'); @@ -816,7 +816,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { test('should lead to the error page for forwarded requests when the connection is refused', async ({ connect, startRemoteServer, browserName }, workerInfo) => { const examplePort = 20_000 + workerInfo.workerIndex * 3; const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: '*' } as any); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: '*' }); const page = await browser.newPage(); const error = await page.goto(`http://127.0.0.1:${examplePort}`).catch(e => e); if (browserName === 'chromium') @@ -837,7 +837,7 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); const examplePort = 20_000 + workerInfo.workerIndex * 3; const remoteServer = await startRemoteServer(kind); - const browser = await connect(remoteServer.wsEndpoint(), { _exposeNetwork: 'localhost' } as any, dummyServerPort); + const browser = await connect(remoteServer.wsEndpoint(), { exposeNetwork: 'localhost' }, dummyServerPort); const page = await browser.newPage(); // localhost should be proxied. @@ -866,11 +866,11 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); const remoteServer = await startRemoteServer(kind); const browser = await connect(remoteServer.wsEndpoint(), { - _exposeNetwork: '127.0.0.1', + exposeNetwork: '127.0.0.1', headers: { 'x-playwright-proxy': '*', }, - } as any, dummyServerPort); + }, dummyServerPort); const page = await browser.newPage(); // local.playwright should fail on the client side. diff --git a/tests/library/playwright.config.ts b/tests/library/playwright.config.ts index 76f84f27c8..1d419115cf 100644 --- a/tests/library/playwright.config.ts +++ b/tests/library/playwright.config.ts @@ -64,7 +64,7 @@ if (mode === 'service2') { connectOptions = { wsEndpoint: `${process.env.PLAYWRIGHT_SERVICE_URL}?accessKey=${process.env.PLAYWRIGHT_SERVICE_ACCESS_KEY}&cap=${JSON.stringify({ os, runId })}`, timeout: 3 * 60 * 1000, - _exposeNetwork: '', + exposeNetwork: '', }; } diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 22ea21e824..28d0a8ff88 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -192,6 +192,22 @@ type ConnectOptions = { */ headers?: { [key: string]: string; }; + /** + * This option exposes network available on the connecting client to the browser being connected to. + * Consists of a list of rules separated by comma. + * + * Available rules: + * - Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`. + * - IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`. + * - `` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. + + * Some common examples: + * - `"*"` to expose all network. + * - `""` to expose localhost network. + * - `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and localhost. + */ + exposeNetwork?: string; + /** * Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout. */