mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-06 03:16:17 +03:00
chore: use own socks5 server for tests (#31639)
This commit is contained in:
parent
2b77ed4d7a
commit
89eef55dc7
152
package-lock.json
generated
152
package-lock.json
generated
@ -58,7 +58,6 @@
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"socksv5": "0.0.6",
|
||||
"ssim.js": "^3.5.0",
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.0.13",
|
||||
@ -2562,12 +2561,6 @@
|
||||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
||||
"integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/asynciterator.prototype": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
|
||||
@ -2826,41 +2819,6 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/cli": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz",
|
||||
"integrity": "sha512-dbn5HyeJWSOU58RwOEiF1VWrl7HRvDsKLpu0uiI/vExH6iNoyUzjB5Mr3IJY5DVUfnbpe9793xw4DFJVzC9nWQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": ">= 3.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/cliff": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz",
|
||||
"integrity": "sha512-roZWcC2Cxo/kKjRXw7YUpVNtxJccbvcl7VzTjUYgLQk6Ot0R8bm2netbhSZYWWNrKlOO/7HD6GXHl8dtzE6SiQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colors": "~1.0.3",
|
||||
"eyes": "~0.1.8",
|
||||
"winston": "0.8.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cliff/node_modules/colors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
|
||||
"integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
@ -3117,15 +3075,6 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"node_modules/cycle": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
|
||||
"integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
@ -3967,15 +3916,6 @@
|
||||
"@types/yauzl": "^2.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eyes": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
|
||||
"integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "> 0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@ -5012,12 +4952,6 @@
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/iterator.prototype": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
|
||||
@ -5843,15 +5777,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/pkginfo": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz",
|
||||
"integrity": "sha512-yO5feByMzAp96LtP58wvPKSbaKAi/1C4kV9XpTctr6EepnP6F33RBNOiVrdz9BrPA98U2BMFsTNHo44TWcbQ2A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"resolved": "packages/playwright",
|
||||
"link": true
|
||||
@ -6511,47 +6436,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/socksv5": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/socksv5/-/socksv5-0.0.6.tgz",
|
||||
"integrity": "sha512-tQpQ0MdNQAsQBDhCXy3OvGGJikh9QOl3PkbwT4POJiQCm/fK4z9AxKQQRG8WLeF6talphnPrSWiZRpTl42rApg==",
|
||||
"bundleDependencies": [
|
||||
"ipv6"
|
||||
],
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ipv6": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socksv5/node_modules/ipv6": {
|
||||
"version": "3.1.1",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cli": "0.4.x",
|
||||
"cliff": "0.1.x",
|
||||
"sprintf": "0.1.x"
|
||||
},
|
||||
"bin": {
|
||||
"ipv6": "bin/ipv6.js",
|
||||
"ipv6grep": "bin/ipv6grep.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/socksv5/node_modules/ipv6/node_modules/sprintf": {
|
||||
"version": "0.1.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"engines": {
|
||||
"node": ">=0.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/solid-js": {
|
||||
"version": "1.8.11",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.11.tgz",
|
||||
@ -6670,15 +6554,6 @@
|
||||
"integrity": "sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
@ -7720,33 +7595,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/winston": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz",
|
||||
"integrity": "sha512-fPoamsHq8leJ62D1M9V/f15mjQ1UHe4+7j1wpAT3fqgA5JqhJkk4aIfPEjfMTI9x6ZTjaLOpMAjluLtmgO5b6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async": "0.2.x",
|
||||
"colors": "0.6.x",
|
||||
"cycle": "1.0.x",
|
||||
"eyes": "0.1.x",
|
||||
"isstream": "0.1.x",
|
||||
"pkginfo": "0.3.x",
|
||||
"stack-trace": "0.0.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/winston/node_modules/colors": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
||||
"integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
@ -96,7 +96,6 @@
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"socksv5": "0.0.6",
|
||||
"ssim.js": "^3.5.0",
|
||||
"typescript": "^5.5.3",
|
||||
"vite": "^5.0.13",
|
||||
|
@ -431,9 +431,9 @@ export class SocksProxy extends EventEmitter implements SocksConnectionClient {
|
||||
return this._port;
|
||||
}
|
||||
|
||||
async listen(port: number): Promise<number> {
|
||||
async listen(port: number, hostname?: string): Promise<number> {
|
||||
return new Promise(f => {
|
||||
this._server.listen(port, () => {
|
||||
this._server.listen(port, hostname, () => {
|
||||
const port = (this._server.address() as AddressInfo).port;
|
||||
this._port = port;
|
||||
f(port);
|
||||
|
@ -16,13 +16,15 @@
|
||||
|
||||
import type { Fixtures } from '@playwright/test';
|
||||
import path from 'path';
|
||||
import socks from 'socksv5';
|
||||
import { TestServer } from './testserver';
|
||||
import { TestProxy } from './proxy';
|
||||
import type { SocksSocketRequestedPayload } from '../../packages/playwright-core/src/common/socksProxy';
|
||||
|
||||
import { SocksProxy } from '../../packages/playwright-core/lib/common/socksProxy';
|
||||
|
||||
export type ServerWorkerOptions = {
|
||||
loopback?: string;
|
||||
__servers: ServerFixtures & { socksServer: socks.SocksServer };
|
||||
__servers: ServerFixtures;
|
||||
};
|
||||
|
||||
export type ServerFixtures = {
|
||||
@ -47,30 +49,9 @@ export const serverFixtures: Fixtures<ServerFixtures, ServerWorkerOptions> = {
|
||||
const httpsServer = await TestServer.createHTTPS(assetsPath, httpsPort, loopback);
|
||||
httpsServer.enableHTTPCache(cachedPath);
|
||||
|
||||
const socksServer = socks.createServer((info, accept, deny) => {
|
||||
const socket = accept(true);
|
||||
if (!socket)
|
||||
return;
|
||||
socket.on('data', data => {
|
||||
if (!data.toString().includes('\r\n\r\n'))
|
||||
return;
|
||||
const body = '<html><title>Served by the SOCKS proxy</title></html>';
|
||||
socket.end([
|
||||
'HTTP/1.1 200 OK',
|
||||
'Connection: close',
|
||||
'Content-Type: text/html',
|
||||
'Content-Length: ' + Buffer.byteLength(body),
|
||||
'',
|
||||
body
|
||||
].join('\r\n'));
|
||||
});
|
||||
// Catch and ignore ECONNRESET errors.
|
||||
socket.on('error', () => {});
|
||||
setTimeout(() => socket.end(), 1000);
|
||||
});
|
||||
const socksServer = new MockSocksServer();
|
||||
const socksPort = port + 2;
|
||||
socksServer.listen(socksPort, 'localhost');
|
||||
socksServer.useAuth(socks.auth.None());
|
||||
await socksServer.listen(socksPort, 'localhost');
|
||||
|
||||
const proxyPort = port + 3;
|
||||
const proxyServer = await TestProxy.create(proxyPort);
|
||||
@ -81,7 +62,6 @@ export const serverFixtures: Fixtures<ServerFixtures, ServerWorkerOptions> = {
|
||||
httpsServer,
|
||||
socksPort,
|
||||
proxyServer,
|
||||
socksServer,
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
@ -116,3 +96,37 @@ export const serverFixtures: Fixtures<ServerFixtures, ServerWorkerOptions> = {
|
||||
},
|
||||
};
|
||||
|
||||
export class MockSocksServer {
|
||||
private _socksProxy: SocksProxy;
|
||||
|
||||
constructor() {
|
||||
this._socksProxy = new SocksProxy();
|
||||
this._socksProxy.setPattern('*');
|
||||
this._socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload: SocksSocketRequestedPayload) => {
|
||||
this._socksProxy.socketConnected({
|
||||
uid: payload.uid,
|
||||
host: '127.0.0.1',
|
||||
port: 0,
|
||||
});
|
||||
const body = '<html><title>Served by the SOCKS proxy</title></html>';
|
||||
const data = Buffer.from([
|
||||
'HTTP/1.1 200 OK',
|
||||
'Connection: close',
|
||||
'Content-Type: text/html',
|
||||
'Content-Length: ' + Buffer.byteLength(body),
|
||||
'',
|
||||
body
|
||||
].join('\r\n'));
|
||||
this._socksProxy.sendSocketData({ uid: payload.uid, data });
|
||||
this._socksProxy.sendSocketEnd({ uid: payload.uid });
|
||||
});
|
||||
}
|
||||
|
||||
async listen(port: number, hostname: string) {
|
||||
await this._socksProxy.listen(port, hostname);
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this._socksProxy.close();
|
||||
}
|
||||
}
|
||||
|
26
tests/index.d.ts
vendored
26
tests/index.d.ts
vendored
@ -1,26 +0,0 @@
|
||||
declare module 'socksv5' {
|
||||
import type net from 'net';
|
||||
|
||||
class Auth { }
|
||||
|
||||
class SocksServer {
|
||||
listen: net.Server['listen'];
|
||||
useAuth(auth: Auth): void;
|
||||
close: net.Server['close'];
|
||||
}
|
||||
|
||||
type Info = {
|
||||
srcAddr: string;
|
||||
srcPort: number;
|
||||
dstAddr: string;
|
||||
dstPort: number;
|
||||
}
|
||||
|
||||
function acceptHandler(intercept: true): net.Socket | undefined;
|
||||
function acceptHandler(intercept: false): undefined;
|
||||
export function createServer(cb: (info: Info, accept: typeof acceptHandler, deny: () => void) => void): SocksServer;
|
||||
|
||||
export const auth: {
|
||||
None: () => Auth
|
||||
};
|
||||
}
|
@ -15,8 +15,9 @@
|
||||
*/
|
||||
|
||||
import { playwrightTest as it, expect } from '../config/browserTest';
|
||||
import socks from 'socksv5';
|
||||
import net from 'net';
|
||||
import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../../packages/playwright-core/src/common/socksProxy';
|
||||
import { SocksProxy } from '../../packages/playwright-core/lib/common/socksProxy';
|
||||
|
||||
it.skip(({ mode }) => mode.startsWith('service'));
|
||||
|
||||
@ -288,28 +289,36 @@ it('should use proxy with emulated user agent', async ({ browserType }) => {
|
||||
expect(requestText).toContain('MyUserAgent');
|
||||
});
|
||||
|
||||
async function setupSocksForwardingServer(port: number, forwardPort: number){
|
||||
const socksServer = socks.createServer((info, accept, deny) => {
|
||||
if (!['127.0.0.1', 'fake-localhost-127-0-0-1.nip.io'].includes(info.dstAddr) || info.dstPort !== 1337) {
|
||||
deny();
|
||||
async function setupSocksForwardingServer(port: number, forwardPort: number) {
|
||||
const connections = new Map<string, net.Socket>();
|
||||
const socksProxy = new SocksProxy();
|
||||
socksProxy.setPattern('*');
|
||||
socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload: SocksSocketRequestedPayload) => {
|
||||
if (!['127.0.0.1', 'fake-localhost-127-0-0-1.nip.io'].includes(payload.host) || payload.port !== 1337) {
|
||||
socksProxy.sendSocketError({ uid: payload.uid, error: 'ECONNREFUSED' });
|
||||
return;
|
||||
}
|
||||
const socket = accept(true);
|
||||
if (socket) {
|
||||
const dstSock = new net.Socket();
|
||||
socket.pipe(dstSock).pipe(socket);
|
||||
socket.on('close', () => dstSock.end());
|
||||
socket.on('end', () => dstSock.end());
|
||||
dstSock.on('error', () => socket.end());
|
||||
dstSock.on('end', () => socket.end());
|
||||
dstSock.setKeepAlive(false);
|
||||
dstSock.connect(forwardPort, '127.0.0.1');
|
||||
}
|
||||
const target = new net.Socket();
|
||||
target.on('error', error => socksProxy.sendSocketError({ uid: payload.uid, error: error.toString() }));
|
||||
target.on('end', () => socksProxy.sendSocketEnd({ uid: payload.uid }));
|
||||
target.on('data', data => socksProxy.sendSocketData({ uid: payload.uid, data }));
|
||||
target.setKeepAlive(false);
|
||||
target.connect(forwardPort, '127.0.0.1');
|
||||
target.on('connect', () => {
|
||||
connections.set(payload.uid, target);
|
||||
socksProxy.socketConnected({ uid: payload.uid, host: target.localAddress, port: target.localPort });
|
||||
});
|
||||
});
|
||||
await new Promise<void>(resolve => socksServer.listen(port, 'localhost', resolve));
|
||||
socksServer.useAuth(socks.auth.None());
|
||||
socksProxy.addListener(SocksProxy.Events.SocksData, async (payload: SocksSocketDataPayload) => {
|
||||
connections.get(payload.uid)?.write(payload.data);
|
||||
});
|
||||
socksProxy.addListener(SocksProxy.Events.SocksClosed, (payload: SocksSocketClosedPayload) => {
|
||||
connections.get(payload.uid)?.destroy();
|
||||
connections.delete(payload.uid);
|
||||
});
|
||||
await socksProxy.listen(port, 'localhost');
|
||||
return {
|
||||
closeProxyServer: () => socksServer.close(),
|
||||
closeProxyServer: () => socksProxy.close(),
|
||||
proxyServerAddr: `socks5://localhost:${port}`,
|
||||
};
|
||||
}
|
||||
@ -343,5 +352,5 @@ it('should use SOCKS proxy for websocket requests', async ({ browserName, platfo
|
||||
expect(value).toBe('incoming');
|
||||
|
||||
await browser.close();
|
||||
closeProxyServer();
|
||||
await closeProxyServer();
|
||||
});
|
||||
|
@ -18,6 +18,6 @@
|
||||
"@web/*": ["packages/web/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["**/*.spec.js", "**/*.ts", "index.d.ts"],
|
||||
"include": ["**/*.spec.js", "**/*.ts"],
|
||||
"exclude": ["components/", "installation/fixture-scripts/"]
|
||||
}
|
||||
|
@ -49,8 +49,10 @@ This project incorporates components from the projects listed below. The origina
|
||||
const allPackages = {};
|
||||
const projectDir = path.join(__dirname, '..', 'packages', project);
|
||||
const bundlesDir = path.join(projectDir, 'bundles');
|
||||
for (const bundle of fs.readdirSync(bundlesDir)) {
|
||||
const dir = path.join(bundlesDir, bundle);
|
||||
for (const bundle of fs.readdirSync(bundlesDir, { withFileTypes: true })) {
|
||||
if (!bundle.isDirectory())
|
||||
continue;
|
||||
const dir = path.join(bundlesDir, bundle.name);
|
||||
execSync('npm ci', { cwd: dir });
|
||||
const packages = await checkDir(dir);
|
||||
for (const [key, value] of Object.entries(packages)) {
|
||||
|
Loading…
Reference in New Issue
Block a user