Puppetter и WebSocket

Проблема: Я скраплю страницу при помощи Puppetter на которой есть несколько Websocket соединений. И одно из соединений представляет собой видеострим который сильно тормозит работу (я запускаю через google cloud function + использую прокси = для меня очень важен вопрос минимизации трафика, ресурсов и скорость выполнения).

Задача: Заблокировать одно из соединений.

Варианты решения:

  • Запретить доступ к этому URL
  • Оборвать соединение после подключения
  • Обернуть нативный WebSocket

Что я попытался сделать

Запретить доступ к этому URL. К сожалению, через page.on('request', () => {}) не видно этих запросов. Об этом есть вот такая ветка https://github.com/puppeteer/puppeteer/issues/2974

Запуская вот так, получаешь все соединения кроме WebSocket

await page.setRequestInterception(true);
page.on('request', async (request) => {
    console.log(request.url());
})

Оборвать соединение после подключения. Здесь я вообще не нашел никаких решений. Я понимаю как при помощи CDPSession получить инфу о WS подключениях, скрапить данные оттуда, но вот если и можно как-то отрубить соединение - я незнаю как.

const session = await page.target().createCDPSession();

const subscribe = async (session: CDPSession) => {
  session.on('sessionattached', (s) => {
    subscribe(s);
  });

  session.send('Network.enable');

  session.on('Network.webSocketCreated', (payload) => {
    console.log('webSocketCreated', payload.url)
  })

  session.send('Runtime.runIfWaitingForDebugger');
}

await session.send('Target.setAutoAttach', {
  autoAttach: true,
  flatten: true,
  waitForDebuggerOnStart: true,
});

subscribe(session);

Что я делать не хочу

Оборачивать нативный WS и самому решать что там делать с подключениями. Я понимаю как это реализовать, но мне очень не хочется идти по этому пути

Буду признателен за любую подсказку!

UPD Страница спрятана за авторизацию, не публичную. Так что дать адрес не могу. Потестировать свое решение можно например вот здесь https://piehost.com/websocket-tester Подключившись к этому Websocket серверу wss://stream.binance.com:9443/ws/etheur@trade


Ответы (1 шт):

Автор решения: Daniil Loban

Решение основано на переопределении метода send, пример снифера на github

Объяснение: в моменте вызова ws.send() узнать url текущего сокета и если он совпадает с искомым — закрыть его.

Приведенный ниже код работает для сервиса из вопроса.

(function () {
    WebSocket.prototype._send = WebSocket.prototype.send;
    WebSocket.prototype.send = function (data) {
    this._send(data); // отсылаем данные через оригинальную функцию
        if (this.url === 'wss://demo.piesocket.com/v3/channel_123?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self')
        this.close()
    }
})()

Воспроизведение:

  • открываем https://piehost.com/websocket-tester
  • производим соединение вебсокета через веб-интерфейс
  • запускаем наш снипет в консоли dev-tools
  • отсылаем сообщение через веб-интерфейс сервиса. введите сюда описание изображения
→ Ссылка