fix: support connectOverCDP over https (#8703)

This commit is contained in:
Yury Semikhatsky 2021-09-03 17:52:22 -07:00 committed by GitHub
parent e5e461c0de
commit 152f6c6f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 1 deletions

View File

@ -34,6 +34,7 @@ import { TimeoutSettings } from '../../utils/timeoutSettings';
import { helper } from '../helper';
import { CallMetadata } from '../instrumentation';
import http from 'http';
import https from 'https';
import { registry } from '../../utils/registry';
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
@ -219,8 +220,9 @@ async function urlToWSEndpoint(endpointURL: string) {
if (endpointURL.startsWith('ws'))
return endpointURL;
const httpURL = endpointURL.endsWith('/') ? `${endpointURL}json/version/` : `${endpointURL}/json/version/`;
const request = endpointURL.startsWith('https') ? https : http;
const json = await new Promise<string>((resolve, reject) => {
http.get(httpURL, resp => {
request.get(httpURL, resp => {
if (resp.statusCode! < 200 || resp.statusCode! >= 400) {
reject(new Error(`Unexpected status ${resp.statusCode} when connecting to ${httpURL}.\n` +
`This does not look like a DevTools server, try connecting via ws://.`));

View File

@ -19,9 +19,44 @@ import { playwrightTest as test, expect } from './config/browserTest';
import fs from 'fs';
import * as path from 'path';
import { getUserAgent } from '../lib/utils/utils';
import WebSocket from 'ws';
test.slow(true, 'All connect tests are slow');
test('should connect over wss', async ({browserType , startRemoteServer, httpsServer}) => {
const remoteServer = await startRemoteServer();
const oldValue = process.env['NODE_TLS_REJECT_UNAUTHORIZED'];
// https://stackoverflow.com/a/21961005/552185
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
try {
httpsServer.onceWebSocketConnection((ws, request) => {
const remote = new WebSocket(remoteServer.wsEndpoint(), [], {
perMessageDeflate: false,
maxPayload: 256 * 1024 * 1024, // 256Mb,
});
const remoteReadyPromise = new Promise<void>((f, r) => {
remote.once('open', f);
remote.once('error', r);
});
remote.on('close', () => ws.close());
remote.on('error', error => ws.close());
remote.on('message', message => ws.send(message));
ws.on('message', async message => {
await remoteReadyPromise;
remote.send(message);
});
ws.on('close', () => remote.close());
ws.on('error', () => remote.close());
});
const browser = await browserType.connect(`wss://localhost:${httpsServer.PORT}/ws`);
expect(browser.version()).toBeTruthy();
await browser.close();
} finally {
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = oldValue;
}
});
test('should be able to reconnect to a browser', async ({browserType, startRemoteServer, server}) => {
const remoteServer = await startRemoteServer();
{

View File

@ -286,6 +286,39 @@ playwrightTest('should report all pages in an existing browser', async ({ browse
}
});
playwrightTest('should connect via https', async ({ browserType, browserOptions, httpsServer }, testInfo) => {
const port = 9339 + testInfo.workerIndex;
const browserServer = await browserType.launch({
...browserOptions,
args: ['--remote-debugging-port=' + port]
});
const json = await new Promise<string>((resolve, reject) => {
http.get(`http://localhost:${port}/json/version/`, resp => {
let data = '';
resp.on('data', chunk => data += chunk);
resp.on('end', () => resolve(data));
}).on('error', reject);
});
httpsServer.setRoute('/json/version/', (req, res) => {
res.writeHead(200);
res.end(json);
});
const oldValue = process.env['NODE_TLS_REJECT_UNAUTHORIZED'];
// https://stackoverflow.com/a/21961005/552185
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
try {
const cdpBrowser = await browserType.connectOverCDP(`https://localhost:${httpsServer.PORT}/`);
const contexts = cdpBrowser.contexts();
expect(contexts.length).toBe(1);
for (let i = 0; i < 3; i++)
await contexts[0].newPage();
await cdpBrowser.close();
} finally {
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = oldValue;
await browserServer.close();
}
});
playwrightTest('should return valid browser from context.browser()', async ({ browserType, browserOptions }, testInfo) => {
const port = 9339 + testInfo.workerIndex;
const browserServer = await browserType.launch({

View File

@ -16,6 +16,7 @@
type ServerResponse = import('http').ServerResponse;
type IncomingMessage = import('http').IncomingMessage;
import WebSocket from 'ws';
export class TestServer {
static create(dirPath: string, port: number, loopback?: string): Promise<TestServer>;
@ -30,6 +31,7 @@ export class TestServer {
setRedirect(from: string, to: string);
waitForRequest(path: string): Promise<IncomingMessage & { postBody: Promise<Buffer> }>;
waitForWebSocketConnectionRequest(): Promise<IncomingMessage>;
onceWebSocketConnection(handler: (ws: WebSocket, request: IncomingMessage) => void);
sendOnWebSocketConnection(data: string);
reset();
serveFile(request: IncomingMessage, response: ServerResponse);

View File

@ -323,6 +323,10 @@ class TestServer {
}
}
onceWebSocketConnection(handler) {
this._wsServer.once('connection', handler);
}
waitForWebSocketConnectionRequest() {
return new Promise(fullfil => {
this._wsServer.once('connection', (ws, req) => fullfil(req));