diff --git a/src/server/browserContext.ts b/src/server/browserContext.ts index 23715e466c..9dcb98fdb4 100644 --- a/src/server/browserContext.ts +++ b/src/server/browserContext.ts @@ -265,8 +265,8 @@ export abstract class BrowserContext extends EventEmitter { if (!proxy) return; const { username, password } = proxy; - if (username && password) - this._options.httpCredentials = { username, password }; + if (username) + this._options.httpCredentials = { username, password: password || '' }; } async _setRequestInterceptor(handler: network.RouteHandler | undefined): Promise { diff --git a/test/browsercontext-proxy.spec.ts b/test/browsercontext-proxy.spec.ts index 82d2605733..67ec26ae94 100644 --- a/test/browsercontext-proxy.spec.ts +++ b/test/browsercontext-proxy.spec.ts @@ -125,6 +125,28 @@ it('should authenticate', async ({contextFactory, contextOptions, server}) => { await browser.close(); }); +it('should authenticate with empty password', async ({contextFactory, contextOptions, server}) => { + server.setRoute('/target.html', async (req, res) => { + const auth = req.headers['proxy-authorization']; + if (!auth) { + res.writeHead(407, 'Proxy Authentication Required', { + 'Proxy-Authenticate': 'Basic realm="Access to internal site"' + }); + res.end(); + } else { + res.end(`${auth}`); + } + }); + const browser = await contextFactory({ + ...contextOptions, + proxy: { server: `localhost:${server.PORT}`, username: 'user', password: '' } + }); + const page = await browser.newPage(); + await page.goto('http://non-existent.com/target.html'); + expect(await page.title()).toBe('Basic ' + Buffer.from('user:').toString('base64')); + await browser.close(); +}); + it('should exclude patterns', (test, { browserName, headful }) => { test.fixme(browserName === 'chromium' && headful, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.'); }, async ({contextFactory, contextOptions, server}) => {