diff --git a/tests/config/proxy.ts b/tests/config/proxy.ts index 42910134fc..67067f8885 100644 --- a/tests/config/proxy.ts +++ b/tests/config/proxy.ts @@ -88,6 +88,10 @@ export class TestProxy { url.host = `127.0.0.1:${port}`; if (options?.prefix) url.pathname = url.pathname.replace(options.prefix, ''); + if (url.protocol === 'ws:') + url.protocol = 'http:'; + else if (url.protocol === 'wss:') + url.protocol = 'https:'; req.url = url.toString(); }); } diff --git a/tests/library/proxy.spec.ts b/tests/library/proxy.spec.ts index b2ddcadeba..b7df2b66f7 100644 --- a/tests/library/proxy.spec.ts +++ b/tests/library/proxy.spec.ts @@ -322,3 +322,37 @@ it('should use SOCKS proxy for websocket requests', async ({ browserType, server await browser.close(); await closeProxyServer(); }); + +it('should use http proxy for websocket requests', async ({ browserName, browserType, server, proxyServer }) => { + proxyServer.forwardTo(server.PORT, { allowConnectRequests: true }); + const browser = await browserType.launch({ + proxy: { server: `localhost:${proxyServer.PORT}` } + }); + + server.sendOnWebSocketConnection('incoming'); + server.setRoute('/target.html', async (req, res) => { + res.end('Served by the proxy'); + }); + + const page = await browser.newPage(); + + await page.goto('http://fake-localhost-127-0-0-1.nip.io:1337/target.html'); + expect(await page.title()).toBe('Served by the proxy'); + + const value = await page.evaluate(() => { + let cb; + const result = new Promise(f => cb = f); + const ws = new WebSocket('ws://fake-localhost-127-0-0-1.nip.io:1337/ws'); + ws.addEventListener('message', data => { ws.close(); cb(data.data); }); + return result; + }); + expect(value).toBe('incoming'); + + // WebKit does not use CONNECT for websockets, but other browsers do. + if (browserName === 'webkit') + expect(proxyServer.wsUrls).toContain('ws://fake-localhost-127-0-0-1.nip.io:1337/ws'); + else + expect(proxyServer.connectHosts).toContain('fake-localhost-127-0-0-1.nip.io:1337'); + + await browser.close(); +}); diff --git a/tests/third_party/proxy/index.ts b/tests/third_party/proxy/index.ts index 6fbd3e9407..e3faaec657 100644 --- a/tests/third_party/proxy/index.ts +++ b/tests/third_party/proxy/index.ts @@ -476,19 +476,21 @@ function onupgrade(req: http.IncomingMessage, socket: net.Socket, head: Buffer) localAddress: this.localAddress, }); + proxyReq.on('error', () => socket.destroy()); proxyReq.on('upgrade', async function (proxyRes, proxySocket, proxyHead) { const header = ['HTTP/1.1 101 Switching Protocols']; for (const [key, value] of Object.entries(proxyRes.headersDistinct)) header.push(`${key}: ${value}`); socket.write(header.join('\r\n') + '\r\n\r\n'); - if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead); + if (proxyHead && proxyHead.length) + proxySocket.unshift(proxyHead); - try { - await pipeline(proxySocket, socket, proxySocket); - } catch (error) { - if (error.code !== "ECONNRESET") - throw error; - } + proxySocket.pipe(socket); + socket.pipe(proxySocket); + proxySocket.on('error', () => socket.destroy()); + socket.on('error', () => proxySocket.destroy()); + proxySocket.on('end', () => socket.end()); + socket.on('end', () => proxySocket.end()); }); proxyReq.end(head);