fix(websockets): filter for text and binary frames (#7360)

This commit is contained in:
Max Schmitt 2021-06-28 21:23:29 +02:00 committed by GitHub
parent 8fa93ae6be
commit 9f9201420a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 6 deletions

View file

@ -442,12 +442,16 @@ export class WebSocket extends ChannelOwner<channels.WebSocketChannel, channels.
this._isClosed = false;
this._page = parent as Page;
this._channel.on('frameSent', (event: { opcode: number, data: string }) => {
const payload = event.opcode === 2 ? Buffer.from(event.data, 'base64') : event.data;
this.emit(Events.WebSocket.FrameSent, { payload });
if (event.opcode === 1)
this.emit(Events.WebSocket.FrameSent, { payload: event.data });
else if (event.opcode === 2)
this.emit(Events.WebSocket.FrameSent, { payload: Buffer.from(event.data, 'base64') });
});
this._channel.on('frameReceived', (event: { opcode: number, data: string }) => {
const payload = event.opcode === 2 ? Buffer.from(event.data, 'base64') : event.data;
this.emit(Events.WebSocket.FrameReceived, { payload });
if (event.opcode === 1)
this.emit(Events.WebSocket.FrameReceived, { payload: event.data });
else if (event.opcode === 2)
this.emit(Events.WebSocket.FrameReceived, { payload: Buffer.from(event.data, 'base64') });
});
this._channel.on('socketError', ({ error }) => this.emit(Events.WebSocket.Error, error));
this._channel.on('close', () => {

View file

@ -72,6 +72,29 @@ it('should emit frame events', async ({ page, server }) => {
expect(log.join(':')).toBe('close:open:received<incoming>:sent<outgoing>');
});
it('should filter out the close events when the server closes with a message', async ({ page, server }) => {
server.sendOnWebSocketConnection('incoming');
let socketClosed;
const socketClosePromise = new Promise(f => socketClosed = f);
const log = [];
page.on('websocket', ws => {
log.push('open');
ws.on('framesent', d => log.push('sent<' + d.payload + '>'));
ws.on('framereceived', d => log.push('received<' + d.payload + '>'));
ws.on('close', () => { log.push('close'); socketClosed(); });
});
await page.evaluate(port => {
const ws = new WebSocket('ws://localhost:' + port + '/ws-emit-and-close');
ws.addEventListener('open', () => ws.send('outgoing'));
ws.addEventListener('message', () => { ws.close(); });
}, server.PORT);
await socketClosePromise;
expect(log[0]).toBe('open');
expect(log[3]).toBe('close');
log.sort();
expect(log.join(':')).toBe('close:open:received<incoming>:sent<outgoing>');
});
it('should pass self as argument to close event', async ({ page, server }) => {
let socketClosed;
const socketClosePromise = new Promise(f => socketClosed = f);

View file

@ -69,10 +69,17 @@ class TestServer {
else
this._server = http.createServer(this._onRequest.bind(this));
this._server.on('connection', socket => this._onSocket(socket));
this._wsServer = new WebSocketServer({server: this._server, path: '/ws'});
this._wsServer.on('connection', ws => {
this._wsServer = new WebSocketServer({server: this._server });
this._wsServer.shouldHandle = (request) => {
const pathname = url.parse(request.url).pathname;
return ['/ws', '/ws-emit-and-close'].includes(pathname);
};
this._wsServer.on('connection', (ws, request) => {
const pathname = url.parse(request.url).pathname;
if (this._onWebSocketConnectionData !== undefined)
ws.send(this._onWebSocketConnectionData);
if (pathname === '/ws-emit-and-close')
ws.close(1003, 'closed by Playwright test-server');
});
this._server.listen(port);
this._dirPath = dirPath;