chore: handle unexpected ws response (#17714)

This commit is contained in:
Pavel Feldman 2022-09-29 13:04:19 -08:00 коммит произвёл GitHub
Родитель a97deb1600
Коммит e09945c637
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 27 добавлений и 3 удалений

Просмотреть файл

@ -17,6 +17,7 @@
import { ws } from '../utilsBundle';
import type { WebSocket } from '../utilsBundle';
import type { ClientRequest, IncomingMessage } from 'http';
import type { Progress } from './progress';
import { makeWaitForNextTask } from '../utils';
@ -62,15 +63,26 @@ export class WebSocketTransport implements ConnectionTransport {
await transport.closeAndWait().catch(e => null);
});
await new Promise<WebSocketTransport>((fulfill, reject) => {
transport._ws.addEventListener('open', async () => {
transport._ws.on('open', async () => {
progress.log(`<ws connected> ${url}`);
fulfill(transport);
});
transport._ws.addEventListener('error', event => {
transport._ws.on('error', event => {
progress.log(`<ws connect error> ${url} ${event.message}`);
reject(new Error('WebSocket error: ' + event.message));
transport._ws.close();
});
transport._ws.on('unexpected-response', (request: ClientRequest, response: IncomingMessage) => {
const chunks: Buffer[] = [];
const errorPrefix = `${url} ${response.statusCode} ${response.statusMessage}`;
response.on('data', chunk => chunks.push(chunk));
response.on('close', () => {
const error = chunks.length ? `${errorPrefix}\n${Buffer.concat(chunks)}` : errorPrefix;
progress.log(`<ws unexpected response> ${error}`);
reject(new Error('WebSocket error: ' + error));
transport._ws.close();
});
});
});
success = true;
return transport;

Просмотреть файл

@ -62,6 +62,13 @@ test('should connect over wss', async ({ browserType, startRemoteServer, httpsSe
}
});
test('should print HTTP error', async ({ browserType, server, mode }) => {
test.skip(mode !== 'default'); // Out of process transport does not allow us to set env vars dynamically.
const error = await browserType.connect(`ws://localhost:${server.PORT}/ws-401`).catch(e => e);
expect(error.message).toContain('401');
expect(error.message).toContain('Unauthorized body');
});
test('should be able to reconnect to a browser', async ({ browserType, startRemoteServer, server }) => {
const remoteServer = await startRemoteServer();
{

Просмотреть файл

@ -57,7 +57,7 @@ it.describe('launch server', () => {
const browserServer = await browserType.launchServer();
const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() + '-foo' }).catch(e => e);
await browserServer.close();
expect(error.message).toContain('Unexpected server response: 400');
expect(error.message).toContain('400 Bad Request');
});
it('should fire "close" event during kill', async ({ browserType }) => {

Просмотреть файл

@ -75,6 +75,11 @@ export class TestServer {
this._wsServer = new ws.WebSocketServer({ noServer: true });
this._server.on('upgrade', async (request, socket, head) => {
const pathname = url.parse(request.url!).path;
if (pathname === '/ws-401') {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\nUnauthorized body');
socket.destroy();
return;
}
if (pathname === '/ws-slow')
await new Promise(f => setTimeout(f, 2000));
if (!['/ws', '/ws-slow'].includes(pathname)) {