Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(launcher): add browserUrl option to puppeteer.connect #3558

Merged
merged 3 commits into from
Jan 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ puppeteer.launch().then(async browser => {

#### puppeteer.connect(options)
- `options` <[Object]>
- `browserWSEndpoint` <[string]> a [browser websocket endpoint](#browserwsendpoint) to connect to.
- `browserWSEndpoint` <?[string]> a [browser websocket endpoint](#browserwsendpoint) to connect to.
- `browserUrl` <?[string]> a browser url to connect to, in format `http://${host}:${port}`. Use interchangeably with `browserWSEndpoint` to let Puppeteer fetch it from [metadata endpoint](https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target).
- `ignoreHTTPSErrors` <[boolean]> Whether to ignore HTTPS errors during navigation. Defaults to `false`.
- `defaultViewport` <?[Object]> Sets a consistent viewport for each page. Defaults to an 800x600 viewport. `null` disables the default viewport.
- `width` <[number]> page width in pixels.
Expand Down Expand Up @@ -3533,4 +3534,4 @@ TimeoutError is emitted whenever certain operations are terminated due to timeou
[Worker]: #class-worker "Worker"
[Accessibility]: #class-accessibility "Accessibility"
[AXNode]: #accessibilitysnapshotoptions "AXNode"
[ConnectionTransport]: ../lib/WebSocketTransport.js "ConnectionTransport"
[ConnectionTransport]: ../lib/WebSocketTransport.js "ConnectionTransport"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a final new line was added at the end of this file, conforming with .editorconfig

65 changes: 62 additions & 3 deletions lib/Launcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
const os = require('os');
const path = require('path');
const http = require('http');
const URL = require('url');
const removeFolder = require('rimraf');
const childProcess = require('child_process');
const BrowserFetcher = require('./BrowserFetcher');
Expand Down Expand Up @@ -274,18 +276,33 @@ class Launcher {
}

/**
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint: string, transport?: !Puppeteer.ConnectionTransport})} options
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserUrl?: string, transport?: !Puppeteer.ConnectionTransport})} options
* @return {!Promise<!Browser>}
*/
async connect(options) {
const {
browserWSEndpoint,
browserUrl,
ignoreHTTPSErrors = false,
defaultViewport = {width: 800, height: 600},
transport = await WebSocketTransport.create(browserWSEndpoint),
transport,
slowMo = 0,
} = options;
const connection = new Connection(browserWSEndpoint, transport, slowMo);

let connectionUrl;
let connectionTransport;

if (browserWSEndpoint)
connectionUrl = browserWSEndpoint;
else if (!browserWSEndpoint && browserUrl)
connectionUrl = await getWSEndpoint(browserUrl);

if (transport)
connectionTransport = transport;
else
connectionTransport = await WebSocketTransport.create(connectionUrl);

const connection = new Connection(connectionUrl, connectionTransport, slowMo);
const {browserContextIds} = await connection.send('Target.getBrowserContexts');
return Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(debugError));
}
Expand Down Expand Up @@ -373,6 +390,48 @@ function waitForWSEndpoint(chromeProcess, timeout, preferredRevision) {
});
}

/**
* @param {string} browserUrl
* @return {!Promise<string>}
*/
function getWSEndpoint(browserUrl) {
let resolve, reject;
const endpointUrl = URL.resolve(browserUrl, '/json/version');
const requestOptions = Object.assign(URL.parse(endpointUrl), { method: 'GET' });
const promise = new Promise((res, rej) => { resolve = res; reject = rej; });

function handleRequestEnd(data) {
try {
const {webSocketDebuggerUrl} = JSON.parse(data);
resolve(webSocketDebuggerUrl);
} catch (e) {
handleRequestError(e);
}
}

function handleRequestError(err) {
reject(new Error(`Failed to fetch browser webSocket url from ${endpointUrl}: ${err}`));
}

const request = http.request(requestOptions, res => {
let data = '';
if (res.statusCode !== 200) {
// consume response data to free up memory
res.resume();
handleRequestError(res.statusCode);
return;
}
res.setEncoding('utf8');
res.on('data', chunk => data += chunk);
res.on('end', () => handleRequestEnd(data));
});

request.on('error', handleRequestError);
request.end();

return promise;
}

/**
* @typedef {Object} Launcher.ChromeArgOptions
* @property {boolean=} headless
Expand Down
2 changes: 1 addition & 1 deletion lib/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = class {
}

/**
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint: string, transport?: !Puppeteer.ConnectionTransport})} options
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserUrl?: string, transport?: !Puppeteer.ConnectionTransport})} options
* @return {!Promise<!Puppeteer.Browser>}
*/
connect(options) {
Expand Down
18 changes: 18 additions & 0 deletions test/puppeteer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,24 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions})
expect(await restoredPage.evaluate(() => 7 * 8)).toBe(56);
await browser.close();
});
it('should be able to connect using browserUrl, with and without trailing slash', async({server}) => {
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
args: ['--remote-debugging-port=21222']
}));
const browserUrl = 'http://127.0.0.1:21222';

const browser1 = await puppeteer.connect({browserUrl});
const page1 = await browser1.newPage();
expect(await page1.evaluate(() => 7 * 8)).toBe(56);
browser1.disconnect();

const browser2 = await puppeteer.connect({browserUrl: browserUrl + '/'});
const page2 = await browser2.newPage();
expect(await page2.evaluate(() => 8 * 7)).toBe(56);
browser2.disconnect();

originalBrowser.close();
});
});
describe('Puppeteer.executablePath', function() {
it('should work', async({server}) => {
Expand Down