如何在 Puppeteer 中拦截服务器发送的事件消息

问题描述 投票:0回答:2

我似乎找不到有关此用例的任何文档。我希望拦截来自我无法控制的源的 SSE 消息,因此我无法将其从服务器发送的事件中更改。

puppeteer
2个回答
3
投票

Puppeteer 没有原生事件来等待 SSE,但您可以使用 Chrome DevTools 协议来执行此操作。参考是here,示例代码如下:

  // some code

  // after you have access to "Page":
  const cdp = await page.target().createCDPSession();
  await cdp.send('Network.enable');
  await cdp.send('Page.enable');
  cdp.on('Network.eventSourceMessageReceived', ({ requestId, timestamp, eventName, eventId, data }) => console.log(requestId, timestamp, eventName, eventId, data));

  // now you can navigate to the page you are testing:
  await page.goto('<url with SSE>');

编辑: 我准备了一个完整的示例,其中有一个扮演 SSE 服务器角色的expressjs 和一个使用事件的 puppeteer 客户端:

const puppeteer = require('puppeteer');
const express = require('express');
const app = express();


app.get('/', (req, res) => {
  res.send(`
    <!DOCTYPE html>
    <body>
      <script>
        var sseSource = new EventSource('/event-stream');
        sseSource.addEventListener('MyEvent', (e) => {
          console.log('[Page] Event Type:', e.type, '| Event Data:', e.data);
        });
      </script>
    </body>
    </html>
  `);
});

app.get('/event-stream', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });
  res.write('\n');
  const intervalId = setInterval(() => {
    res.write(`event: MyEvent\n`);
    res.write(`data: Test Message received at ${Date.now()}\n\n`);
  }, 1000);
  req.on('close', () => clearInterval(intervalId));
});

const server = app.listen(8080, async () => {
  const browser = await puppeteer.launch();

  const page = await browser.newPage();
  await page.setDefaultTimeout(0);

  const cdp = await page.target().createCDPSession();
  await cdp.send('Network.enable');
  await cdp.send('Page.enable');
  cdp.on('Network.eventSourceMessageReceived', ({ eventName, data }) => console.log(`[Node] Event Type: ${eventName} | Event Data: ${data}\n`));
  page.on('console', (msg) => console.log(msg.text()));
  await page.goto('http://localhost:8080/');
  await page.waitFor(300000); // 5 minutes
  await page.close();
  await browser.close();
  server.close();
});

0
投票

您可以使用 Network.streamResourceContent 来检索 EventStream 数据。有关参考,请参阅文档链接:https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-streamResourceContent

示例代码:

cdp.on('Network.responseReceived', async response => {
    this.#stream_resource_content_handler(response, cdp);
});

async #stream_resource_content_handler(response, cdp) {
    try {
        const {bufferedData} = await cdp.send('Network.streamResourceContent', {
            requestId: response.requestId,
        });

    } catch (error) {
        // Handle error
    }
}

cdp.on('Network.dataReceived', async response => {
    console.log(response);
});

注意:从Network.dataReceived获取的数据是base64编码的。

© www.soinside.com 2019 - 2024. All rights reserved.