diff --git a/packages/playwright-core/src/server/browser.ts b/packages/playwright-core/src/server/browser.ts index 66546b7f4bf63..b2446893519c1 100644 --- a/packages/playwright-core/src/server/browser.ts +++ b/packages/playwright-core/src/server/browser.ts @@ -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'; @@ -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)); diff --git a/packages/playwright-core/src/server/browserContext.ts b/packages/playwright-core/src/server/browserContext.ts index 5cde633b4bd89..cd59af0ba7fe0 100644 --- a/packages/playwright-core/src/server/browserContext.ts +++ b/packages/playwright-core/src/server/browserContext.ts @@ -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; diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index bed4f1d3e86a4..42360d96ef4b6 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -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 }; diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 4905f22f8369a..c7bb3a8c53912 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -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) { @@ -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); diff --git a/tests/library/browsercontext-proxy.spec.ts b/tests/library/browsercontext-proxy.spec.ts index c5f25e3f5a156..c0861471a6b1d 100644 --- a/tests/library/browsercontext-proxy.spec.ts +++ b/tests/library/browsercontext-proxy.spec.ts @@ -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