Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions packages/playwright-core/src/server/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import fs from 'fs';

import { makeSocketPath } from '@utils/fileUtils';
import { createGuid } from '@utils/crypto';
import { BrowserContext, validateBrowserContextOptions } from './browserContext';
import { BrowserContext, effectiveProxy, validateBrowserContextOptions } from './browserContext';
import { Download } from './download';
import { SdkObject } from './instrumentation';
import { Page } from './page';
Expand Down Expand Up @@ -108,10 +108,8 @@ export abstract class Browser extends SdkObject {
let context: BrowserContext | undefined;
try {
if (options.clientCertificates?.length) {
clientCertificatesProxy = await ClientCertificatesProxy.create(progress, options);
options = { ...options };
options.proxyOverride = clientCertificatesProxy.proxySettings();
options.internalIgnoreHTTPSErrors = true;
clientCertificatesProxy = await ClientCertificatesProxy.create(progress, { ...options, proxy: effectiveProxy(options.proxy, this.options.proxy) });
options = { ...options, proxyOverride: clientCertificatesProxy.proxySettings(), internalIgnoreHTTPSErrors: true };
}
context = await progress.race(this.doCreateNewContext(options));
context._clientCertificatesProxy = clientCertificatesProxy;
Expand Down
4 changes: 4 additions & 0 deletions packages/playwright-core/src/server/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,10 @@ export function verifyClientCertificates(clientCertificates?: types.BrowserConte
}
}

export function effectiveProxy(contextProxy: types.ProxySettings | undefined, launchProxy: types.ProxySettings | undefined): types.ProxySettings | undefined {
return contextProxy || (launchProxy?.server === 'per-context' ? undefined : launchProxy);
}

export function normalizeProxySettings(proxy: types.ProxySettings): types.ProxySettings {
let { server, bypass } = proxy;
let url;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,10 @@ export class ClientCertificatesProxy {
}

_getProxyAgent(host: string, port: number) {
const proxyFromOptions = createProxyAgent(this._proxy);
if (proxyFromOptions)
return proxyFromOptions;
const proxyFromEnv = getProxyForUrl(`https://${host}:${port}`);
const url = new URL(`https://${net.isIPv6(host) ? `[${host}]` : host}:${port}`);
if (this._proxy)
return createProxyAgent(this._proxy, url);
const proxyFromEnv = getProxyForUrl(url.href);
if (proxyFromEnv)
return createProxyAgent({ server: proxyFromEnv });
}
Expand Down
30 changes: 30 additions & 0 deletions tests/library/client-certificates.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,36 @@ test.describe('browser', () => {
delete process.env.HTTPS_PROXY;
});

test('should respect launch proxy and proxy bypass', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42806' } }, async ({ browserType, startCCServer, asset, browserName, proxyServer, isMac }) => {
const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac });
const { origin, hostname, port } = new URL(serverURL);
proxyServer.forwardTo(parseInt(port, 10), { allowConnectRequests: true });
const proxy = { server: `localhost:${proxyServer.PORT}` };
const clientCertificates = [{
origin,
certPath: asset('client-certificates/client/trusted/cert.pem'),
keyPath: asset('client-certificates/client/trusted/key.pem'),
}];
const browser = await browserType.launch({ proxy });
{
const page = await browser.newPage({ ignoreHTTPSErrors: true, clientCertificates });
await page.goto(serverURL);
await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!');
const host = browserName === 'webkit' && isMac ? 'localhost' : '127.0.0.1';
expect([...new Set(proxyServer.connectHosts)]).toEqual([`${host}:${port}`]);
await page.close();
}
proxyServer.connectHosts = [];
{
const page = await browser.newPage({ ignoreHTTPSErrors: true, clientCertificates, proxy: { ...proxy, bypass: hostname } });
await page.goto(serverURL);
await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!');
expect(proxyServer.connectHosts).toEqual([]);
await page.close();
}
await browser.close();
});

test('should pass with matching certificates and when a socks proxy is used', async ({ browser, startCCServer, asset, browserName, isMac }) => {
const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac });
const serverPort = parseInt(new URL(serverURL).port, 10);
Expand Down
Loading