feat(proxy): bind proxy to open port (#8331)
This commit is contained in:
parent
70eca0401d
commit
80dded6ccf
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net from 'net';
|
import net, { AddressInfo } from 'net';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import { Playwright } from '../server/playwright';
|
import { Playwright } from '../server/playwright';
|
||||||
import { AndroidDispatcher } from './androidDispatcher';
|
import { AndroidDispatcher } from './androidDispatcher';
|
||||||
|
|
@ -25,6 +25,7 @@ import { SelectorsDispatcher } from './selectorsDispatcher';
|
||||||
import * as types from '../server/types';
|
import * as types from '../server/types';
|
||||||
import { SocksConnection, SocksConnectionClient } from '../utils/socksProxy';
|
import { SocksConnection, SocksConnectionClient } from '../utils/socksProxy';
|
||||||
import { createGuid } from '../utils/utils';
|
import { createGuid } from '../utils/utils';
|
||||||
|
import { debugLogger } from '../utils/debugLogger';
|
||||||
|
|
||||||
export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.PlaywrightInitializer> implements channels.PlaywrightChannel {
|
export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.PlaywrightInitializer> implements channels.PlaywrightChannel {
|
||||||
private _socksProxy: SocksProxy | undefined;
|
private _socksProxy: SocksProxy | undefined;
|
||||||
|
|
@ -45,9 +46,10 @@ export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.Playwr
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
enableSocksProxy(port: number) {
|
async enableSocksProxy() {
|
||||||
this._socksProxy = new SocksProxy(this);
|
this._socksProxy = new SocksProxy(this);
|
||||||
this._socksProxy.listen(port);
|
this._object.options.socksProxyPort = await this._socksProxy.listen(0);
|
||||||
|
debugLogger.log('proxy', `Starting socks proxy server on port ${this._object.options.socksProxyPort}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async socksConnected(params: channels.PlaywrightSocksConnectedParams, metadata?: channels.Metadata): Promise<void> {
|
async socksConnected(params: channels.PlaywrightSocksConnectedParams, metadata?: channels.Metadata): Promise<void> {
|
||||||
|
|
@ -85,8 +87,12 @@ class SocksProxy implements SocksConnectionClient {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(port: number) {
|
async listen(port: number): Promise<number> {
|
||||||
this._server.listen(port);
|
return new Promise(f => {
|
||||||
|
this._server.listen(port, () => {
|
||||||
|
f((this._server.address() as AddressInfo).port);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onSocketRequested(uid: string, host: string, port: number): void {
|
onSocketRequested(uid: string, host: string, port: number): void {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export class PlaywrightServer {
|
||||||
playwright = createPlaywright();
|
playwright = createPlaywright();
|
||||||
const dispatcher = new PlaywrightDispatcher(rootScope, playwright);
|
const dispatcher = new PlaywrightDispatcher(rootScope, playwright);
|
||||||
if (process.env.PW_SOCKS_PROXY_PORT)
|
if (process.env.PW_SOCKS_PROXY_PORT)
|
||||||
dispatcher.enableSocksProxy(+process.env.PW_SOCKS_PROXY_PORT);
|
await dispatcher.enableSocksProxy();
|
||||||
return dispatcher;
|
return dispatcher;
|
||||||
});
|
});
|
||||||
return () => {
|
return () => {
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,9 @@ export interface BrowserProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlaywrightOptions = {
|
export type PlaywrightOptions = {
|
||||||
rootSdkObject: SdkObject,
|
rootSdkObject: SdkObject;
|
||||||
selectors: Selectors,
|
selectors: Selectors;
|
||||||
|
socksProxyPort?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BrowserOptions = PlaywrightOptions & {
|
export type BrowserOptions = PlaywrightOptions & {
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
async launch(metadata: CallMetadata, options: types.LaunchOptions, protocolLogger?: types.ProtocolLogger): Promise<Browser> {
|
async launch(metadata: CallMetadata, options: types.LaunchOptions, protocolLogger?: types.ProtocolLogger): Promise<Browser> {
|
||||||
options = validateLaunchOptions(options);
|
options = this._validateLaunchOptions(options);
|
||||||
const controller = new ProgressController(metadata, this);
|
const controller = new ProgressController(metadata, this);
|
||||||
controller.setLogName('browser');
|
controller.setLogName('browser');
|
||||||
const browser = await controller.run(progress => {
|
const browser = await controller.run(progress => {
|
||||||
|
|
@ -63,7 +63,7 @@ export abstract class BrowserType extends SdkObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: types.LaunchPersistentOptions): Promise<BrowserContext> {
|
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: types.LaunchPersistentOptions): Promise<BrowserContext> {
|
||||||
options = validateLaunchOptions(options);
|
options = this._validateLaunchOptions(options);
|
||||||
const controller = new ProgressController(metadata, this);
|
const controller = new ProgressController(metadata, this);
|
||||||
const persistent: types.BrowserContextOptions = options;
|
const persistent: types.BrowserContextOptions = options;
|
||||||
controller.setLogName('browser');
|
controller.setLogName('browser');
|
||||||
|
|
@ -243,6 +243,18 @@ export abstract class BrowserType extends SdkObject {
|
||||||
throw new Error('CDP connections are only supported by Chromium');
|
throw new Error('CDP connections are only supported by Chromium');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _validateLaunchOptions<Options extends types.LaunchOptions>(options: Options): Options {
|
||||||
|
const { devtools = false } = options;
|
||||||
|
let { headless = !devtools, downloadsPath, proxy } = options;
|
||||||
|
if (debugMode())
|
||||||
|
headless = false;
|
||||||
|
if (downloadsPath && !path.isAbsolute(downloadsPath))
|
||||||
|
downloadsPath = path.join(process.cwd(), downloadsPath);
|
||||||
|
if (this._playwrightOptions.socksProxyPort)
|
||||||
|
proxy = { server: `socks5://127.0.0.1:${this._playwrightOptions.socksProxyPort}` };
|
||||||
|
return { ...options, devtools, headless, downloadsPath, proxy };
|
||||||
|
}
|
||||||
|
|
||||||
abstract _defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[];
|
abstract _defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[];
|
||||||
abstract _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<Browser>;
|
abstract _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<Browser>;
|
||||||
abstract _amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env;
|
abstract _amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env;
|
||||||
|
|
@ -256,15 +268,3 @@ function copyTestHooks(from: object, to: object) {
|
||||||
(to as any)[key] = value;
|
(to as any)[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateLaunchOptions<Options extends types.LaunchOptions>(options: Options): Options {
|
|
||||||
const { devtools = false } = options;
|
|
||||||
let { headless = !devtools, downloadsPath, proxy } = options;
|
|
||||||
if (debugMode())
|
|
||||||
headless = false;
|
|
||||||
if (downloadsPath && !path.isAbsolute(downloadsPath))
|
|
||||||
downloadsPath = path.join(process.cwd(), downloadsPath);
|
|
||||||
if (process.env.PW_SOCKS_PROXY_PORT)
|
|
||||||
proxy = { server: `socks5://127.0.0.1:${process.env.PW_SOCKS_PROXY_PORT}` };
|
|
||||||
return { ...options, devtools, headless, downloadsPath, proxy };
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -163,14 +163,14 @@ export class Chromium extends BrowserType {
|
||||||
const proxyURL = new URL(proxy.server);
|
const proxyURL = new URL(proxy.server);
|
||||||
const isSocks = proxyURL.protocol === 'socks5:';
|
const isSocks = proxyURL.protocol === 'socks5:';
|
||||||
// https://www.chromium.org/developers/design-documents/network-settings
|
// https://www.chromium.org/developers/design-documents/network-settings
|
||||||
if (isSocks && !process.env.PW_SOCKS_PROXY_PORT) {
|
if (isSocks && !this._playwrightOptions.socksProxyPort) {
|
||||||
// https://www.chromium.org/developers/design-documents/network-stack/socks-proxy
|
// https://www.chromium.org/developers/design-documents/network-stack/socks-proxy
|
||||||
chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`);
|
chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`);
|
||||||
}
|
}
|
||||||
chromeArguments.push(`--proxy-server=${proxy.server}`);
|
chromeArguments.push(`--proxy-server=${proxy.server}`);
|
||||||
const proxyBypassRules = [];
|
const proxyBypassRules = [];
|
||||||
// https://source.chromium.org/chromium/chromium/src/+/master:net/docs/proxy.md;l=548;drc=71698e610121078e0d1a811054dcf9fd89b49578
|
// https://source.chromium.org/chromium/chromium/src/+/master:net/docs/proxy.md;l=548;drc=71698e610121078e0d1a811054dcf9fd89b49578
|
||||||
if (process.env.PW_SOCKS_PROXY_PORT)
|
if (this._playwrightOptions.socksProxyPort)
|
||||||
proxyBypassRules.push('<-loopback>');
|
proxyBypassRules.push('<-loopback>');
|
||||||
if (proxy.bypass)
|
if (proxy.bypass)
|
||||||
proxyBypassRules.push(...proxy.bypass.split(',').map(t => t.trim()).map(t => t.startsWith('.') ? '*' + t : t));
|
proxyBypassRules.push(...proxy.bypass.split(',').map(t => t.trim()).map(t => t.startsWith('.') ? '*' + t : t));
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class OutOfProcessPlaywrightServer {
|
||||||
detached: true,
|
detached: true,
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
PW_SOCKS_PROXY_PORT: String(proxyPort)
|
PW_SOCKS_PROXY_PORT: '1'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._driverProcess.unref();
|
this._driverProcess.unref();
|
||||||
|
|
@ -44,6 +44,9 @@ class OutOfProcessPlaywrightServer {
|
||||||
if (line.startsWith(prefix))
|
if (line.startsWith(prefix))
|
||||||
resolve(line.substr(prefix.length));
|
resolve(line.substr(prefix.length));
|
||||||
});
|
});
|
||||||
|
this._driverProcess.stderr.on('data', (data: Buffer) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
this._driverProcess.on('exit', () => reject());
|
this._driverProcess.on('exit', () => reject());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue