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
4 changes: 2 additions & 2 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, effectiveProxy, validateBrowserContextOptions } from './browserContext';
import { BrowserContext, validateBrowserContextOptions } from './browserContext';
import { Download } from './download';
import { SdkObject } from './instrumentation';
import { Page } from './page';
Expand Down Expand Up @@ -108,7 +108,7 @@ export abstract class Browser extends SdkObject {
let context: BrowserContext | undefined;
try {
if (options.clientCertificates?.length) {
clientCertificatesProxy = await ClientCertificatesProxy.create(progress, { ...options, proxy: effectiveProxy(options.proxy, this.options.proxy) });
clientCertificatesProxy = await ClientCertificatesProxy.create(progress, { ...options, proxy: options.proxy || this.options.proxy });
options = { ...options, proxyOverride: clientCertificatesProxy.proxySettings(), internalIgnoreHTTPSErrors: true };
}
context = await progress.race(this.doCreateNewContext(options));
Expand Down
4 changes: 0 additions & 4 deletions packages/playwright-core/src/server/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -828,10 +828,6 @@ 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
3 changes: 3 additions & 0 deletions packages/playwright-core/src/server/browserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ export abstract class BrowserType extends SdkObject {
headless = false;
if (downloadsPath && !path.isAbsolute(downloadsPath))
downloadsPath = path.join(process.cwd(), downloadsPath);
// Legacy placeholder for "every context sets its own proxy", no longer required.
if (proxy?.server === 'per-context' || proxy?.server === 'http://per-context')
proxy = undefined;
if (options.socksProxyPort)
proxy = { server: `socks5://127.0.0.1:${options.socksProxyPort}` };
return { ...options, headless, downloadsPath, proxy };
Expand Down
9 changes: 1 addition & 8 deletions packages/playwright-core/src/server/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,6 @@ export abstract class APIRequestContext extends SdkObject {
this.emit(APIRequestContext.Events.Dispose);
}

private _proxyAgentForUrl(url: URL): http.Agent | undefined {
const proxy = this._defaultOptions().proxy;
// We skip 'per-context' in order to not break existing users. 'per-context' was previously used to
// workaround an upstream Chromium bug. Can be removed in the future.
return createProxyAgent(proxy?.server === 'per-context' ? undefined : proxy, url);
}

private _ensureAgent(protocol: string): http.Agent {
let agent = this._agentForProtocol.get(protocol);
if (!agent) {
Expand Down Expand Up @@ -367,7 +360,7 @@ export abstract class APIRequestContext extends SdkObject {
...options,
...happyEyeballsOptions,
...getMatchingTLSOptionsForOrigin(this._defaultOptions().clientCertificates, url.origin),
agent: this._proxyAgentForUrl(url) ?? this._ensureAgent(url.protocol),
agent: createProxyAgent(this._defaultOptions().proxy, url) ?? this._ensureAgent(url.protocol),
};
if (options.__testHookLookup)
requestOptions.lookup = lookupWithTestHook(options.__testHookLookup);
Expand Down
25 changes: 25 additions & 0 deletions tests/library/browsercontext-proxy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,31 @@ it('should work when passing the proxy only on the context level', async ({ brow
}
});

for (const launchProxy of ['per-context', 'http://per-context']) {
it(`should ignore legacy '${launchProxy}' launch proxy`, async ({ browserType, server, proxyServer }) => {
proxyServer.forwardTo(server.PORT, { allowConnectRequests: true });
const browser = await browserType.launch({ proxy: { server: launchProxy } });
try {
const context = await browser.newContext({ proxy: { server: proxyServer.HOST } });
const page = await context.newPage();
await page.goto('http://non-existent.com/target.html');
expect(await page.title()).toBe('Served by the proxy');
const response = await context.request.get('http://non-existent.com/target.html');
expect(await response.text()).toContain('Served by the proxy');
expect(proxyServer.connectHosts).toContain('non-existent.com:80');

const directContext = await browser.newContext();
const directPage = await directContext.newPage();
await directPage.goto(server.PREFIX + '/target.html');
expect(await directPage.title()).toBe('Served by the proxy');
const directResponse = await directContext.request.get(server.PREFIX + '/target.html');
expect(directResponse.ok()).toBe(true);
} finally {
await browser.close();
}
});
}

it('should throw for bad server value', async ({ contextFactory }) => {
const error = await contextFactory({
// @ts-expect-error server must be a string
Expand Down
Loading