feat(connect): exposeNetwork option (#24436)
This commit is contained in:
parent
ececb6d19e
commit
ea6d127f28
|
|
@ -124,6 +124,22 @@ Logger sink for Playwright logging. Optional.
|
||||||
Maximum time in milliseconds to wait for the connection to be established. Defaults to
|
Maximum time in milliseconds to wait for the connection to be established. Defaults to
|
||||||
`0` (no timeout).
|
`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. `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
|
||||||
|
|
||||||
|
Some common examples:
|
||||||
|
1. `"*"` to expose all network.
|
||||||
|
1. `"<loopback>"` to expose localhost network.
|
||||||
|
1. `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and localhost.
|
||||||
|
|
||||||
## async method: BrowserType.connectOverCDP
|
## async method: BrowserType.connectOverCDP
|
||||||
* since: v1.9
|
* since: v1.9
|
||||||
- returns: <[Browser]>
|
- returns: <[Browser]>
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
'x-playwright-launch-options': jsonStringifyForceASCII({ ...this._defaultLaunchOptions, ...launchOptions }),
|
'x-playwright-launch-options': jsonStringifyForceASCII({ ...this._defaultLaunchOptions, ...launchOptions }),
|
||||||
...connectOptions.headers,
|
...connectOptions.headers,
|
||||||
},
|
},
|
||||||
_exposeNetwork: connectOptions._exposeNetwork,
|
exposeNetwork: connectOptions.exposeNetwork ?? connectOptions._exposeNetwork,
|
||||||
slowMo: connectOptions.slowMo,
|
slowMo: connectOptions.slowMo,
|
||||||
timeout: connectOptions.timeout ?? 3 * 60 * 1000, // 3 minutes
|
timeout: connectOptions.timeout ?? 3 * 60 * 1000, // 3 minutes
|
||||||
});
|
});
|
||||||
|
|
@ -149,7 +149,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
const connectParams: channels.LocalUtilsConnectParams = {
|
const connectParams: channels.LocalUtilsConnectParams = {
|
||||||
wsEndpoint: params.wsEndpoint,
|
wsEndpoint: params.wsEndpoint,
|
||||||
headers,
|
headers,
|
||||||
exposeNetwork: params._exposeNetwork,
|
exposeNetwork: params.exposeNetwork ?? params._exposeNetwork,
|
||||||
slowMo: params.slowMo,
|
slowMo: params.slowMo,
|
||||||
timeout: params.timeout,
|
timeout: params.timeout,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ export type LaunchPersistentContextOptions = Omit<LaunchOptionsBase & BrowserCon
|
||||||
export type ConnectOptions = {
|
export type ConnectOptions = {
|
||||||
wsEndpoint: string,
|
wsEndpoint: string,
|
||||||
headers?: { [key: string]: string; };
|
headers?: { [key: string]: string; };
|
||||||
|
exposeNetwork?: string,
|
||||||
_exposeNetwork?: string,
|
_exposeNetwork?: string,
|
||||||
slowMo?: number,
|
slowMo?: number,
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
|
|
|
||||||
17
packages/playwright-core/types/types.d.ts
vendored
17
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -19640,6 +19640,23 @@ export interface ConnectOverCDPOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnectOptions {
|
export interface ConnectOptions {
|
||||||
|
/**
|
||||||
|
* 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. `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
|
||||||
|
*
|
||||||
|
* Some common examples:
|
||||||
|
* 1. `"*"` to expose all network.
|
||||||
|
* 1. `"<loopback>"` to expose localhost network.
|
||||||
|
* 1. `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and
|
||||||
|
* localhost.
|
||||||
|
*/
|
||||||
|
exposeNetwork?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional HTTP headers to be sent with web socket connect request. Optional.
|
* Additional HTTP headers to be sent with web socket connect request. Optional.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ function connectOptionsFromEnv() {
|
||||||
return {
|
return {
|
||||||
wsEndpoint,
|
wsEndpoint,
|
||||||
headers,
|
headers,
|
||||||
_exposeNetwork: process.env.PW_TEST_CONNECT_EXPOSE_NETWORK,
|
exposeNetwork: process.env.PW_TEST_CONNECT_EXPOSE_NETWORK,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
packages/playwright-test/types/test.d.ts
vendored
16
packages/playwright-test/types/test.d.ts
vendored
|
|
@ -3392,6 +3392,22 @@ type ConnectOptions = {
|
||||||
*/
|
*/
|
||||||
headers?: { [key: string]: string; };
|
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`.
|
||||||
|
* - `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
|
||||||
|
|
||||||
|
* Some common examples:
|
||||||
|
* - `"*"` to expose all network.
|
||||||
|
* - `"<loopback>"` to expose localhost network.
|
||||||
|
* - `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and localhost.
|
||||||
|
*/
|
||||||
|
exposeNetwork?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout.
|
* Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -736,7 +736,7 @@ for (const kind of ['launchServer', 'run-server'] as const) {
|
||||||
res.end('<html><body>original-target</body></html>');
|
res.end('<html><body>original-target</body></html>');
|
||||||
});
|
});
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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 page = await browser.newPage();
|
||||||
await page.goto(server.PREFIX + '/foo.html');
|
await page.goto(server.PREFIX + '/foo.html');
|
||||||
expect(await page.content()).toContain('original-target');
|
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 examplePort = 20_000 + testInfo.workerIndex * 3;
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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();
|
const page = await browser.newPage();
|
||||||
await page.goto(`http://[::1]:${examplePort}/foo.html`);
|
await page.goto(`http://[::1]:${examplePort}/foo.html`);
|
||||||
expect(await page.content()).toContain('from-ipv6-server');
|
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 examplePort = 20_000 + workerInfo.workerIndex * 3;
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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 page = await browser.newPage();
|
||||||
const response = await page.request.get(`http://127.0.0.1:${examplePort}/foo.html`);
|
const response = await page.request.get(`http://127.0.0.1:${examplePort}/foo.html`);
|
||||||
expect(response.status()).toBe(200);
|
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 examplePort = 20_000 + workerInfo.workerIndex * 3;
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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 page = await browser.newPage();
|
||||||
await page.goto(`http://local.playwright:${examplePort}/foo.html`);
|
await page.goto(`http://local.playwright:${examplePort}/foo.html`);
|
||||||
expect(await page.content()).toContain('from-dummy-server');
|
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) => {
|
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 examplePort = 20_000 + workerInfo.workerIndex * 3;
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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 page = await browser.newPage();
|
||||||
const error = await page.goto(`http://127.0.0.1:${examplePort}`).catch(e => e);
|
const error = await page.goto(`http://127.0.0.1:${examplePort}`).catch(e => e);
|
||||||
if (browserName === 'chromium')
|
if (browserName === 'chromium')
|
||||||
|
|
@ -837,7 +837,7 @@ for (const kind of ['launchServer', 'run-server'] as const) {
|
||||||
});
|
});
|
||||||
const examplePort = 20_000 + workerInfo.workerIndex * 3;
|
const examplePort = 20_000 + workerInfo.workerIndex * 3;
|
||||||
const remoteServer = await startRemoteServer(kind);
|
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();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
// localhost should be proxied.
|
// localhost should be proxied.
|
||||||
|
|
@ -866,11 +866,11 @@ for (const kind of ['launchServer', 'run-server'] as const) {
|
||||||
});
|
});
|
||||||
const remoteServer = await startRemoteServer(kind);
|
const remoteServer = await startRemoteServer(kind);
|
||||||
const browser = await connect(remoteServer.wsEndpoint(), {
|
const browser = await connect(remoteServer.wsEndpoint(), {
|
||||||
_exposeNetwork: '127.0.0.1',
|
exposeNetwork: '127.0.0.1',
|
||||||
headers: {
|
headers: {
|
||||||
'x-playwright-proxy': '*',
|
'x-playwright-proxy': '*',
|
||||||
},
|
},
|
||||||
} as any, dummyServerPort);
|
}, dummyServerPort);
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
|
||||||
// local.playwright should fail on the client side.
|
// local.playwright should fail on the client side.
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ if (mode === 'service2') {
|
||||||
connectOptions = {
|
connectOptions = {
|
||||||
wsEndpoint: `${process.env.PLAYWRIGHT_SERVICE_URL}?accessKey=${process.env.PLAYWRIGHT_SERVICE_ACCESS_KEY}&cap=${JSON.stringify({ os, runId })}`,
|
wsEndpoint: `${process.env.PLAYWRIGHT_SERVICE_URL}?accessKey=${process.env.PLAYWRIGHT_SERVICE_ACCESS_KEY}&cap=${JSON.stringify({ os, runId })}`,
|
||||||
timeout: 3 * 60 * 1000,
|
timeout: 3 * 60 * 1000,
|
||||||
_exposeNetwork: '<loopback>',
|
exposeNetwork: '<loopback>',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
utils/generate_types/overrides-test.d.ts
vendored
16
utils/generate_types/overrides-test.d.ts
vendored
|
|
@ -192,6 +192,22 @@ type ConnectOptions = {
|
||||||
*/
|
*/
|
||||||
headers?: { [key: string]: string; };
|
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`.
|
||||||
|
* - `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
|
||||||
|
|
||||||
|
* Some common examples:
|
||||||
|
* - `"*"` to expose all network.
|
||||||
|
* - `"<loopback>"` to expose localhost network.
|
||||||
|
* - `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and localhost.
|
||||||
|
*/
|
||||||
|
exposeNetwork?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout.
|
* Timeout in milliseconds for the connection to be established. Optional, defaults to no timeout.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue