使用 devtool 协议从嵌入式 iframe 捕获请求(XHR、JS、CSS)
Capture requests (XHR, JS, CSS) from embedded iframes using devtool protocol
就上下文而言,我正在使用 Nodejs 和 puppeteer 开发一个综合监控工具。
对于定义场景的每个步骤,我都会捕获屏幕截图、瀑布和性能指标。
我的问题出在瀑布上,我以前使用过 puppeter-har,但这个包无法捕获导航之外的请求。
因此我使用这段代码来捕获所有有趣的请求:
const {harFromMessages} = require('chrome-har');
// Event types to observe for waterfall saving (probably overkill, I just set all events of Page and Network)
const observe = [
'Page.domContentEventFired',
'Page.fileChooserOpened',
'Page.frameAttached',
'Page.frameDetached',
'Page.frameNavigated',
'Page.interstitialHidden',
'Page.interstitialShown',
'Page.javascriptDialogClosed',
'Page.javascriptDialogOpening',
'Page.lifecycleEvent',
'Page.loadEventFired',
'Page.windowOpen',
'Page.frameClearedScheduledNavigation',
'Page.frameScheduledNavigation',
'Page.compilationCacheProduced',
'Page.downloadProgress',
'Page.downloadWillBegin',
'Page.frameRequestedNavigation',
'Page.frameResized',
'Page.frameStartedLoading',
'Page.frameStoppedLoading',
'Page.navigatedWithinDocument',
'Page.screencastFrame',
'Page.screencastVisibilityChanged',
'Network.dataReceived',
'Network.eventSourceMessageReceived',
'Network.loadingFailed',
'Network.loadingFinished',
'Network.requestServedFromCache',
'Network.requestWillBeSent',
'Network.responseReceived',
'Network.webSocketClosed',
'Network.webSocketCreated',
'Network.webSocketFrameError',
'Network.webSocketFrameReceived',
'Network.webSocketFrameSent',
'Network.webSocketHandshakeResponseReceived',
'Network.webSocketWillSendHandshakeRequest',
'Network.requestWillBeSentExtraInfo',
'Network.resourceChangedPriority',
'Network.responseReceivedExtraInfo',
'Network.signedExchangeReceived',
'Network.requestIntercepted'
];
步骤开始时:
// list of events for converting to HAR
const events = [];
client = await page.target().createCDPSession();
await client.send('Page.enable');
await client.send('Network.enable');
observe.forEach(method => {
client.on(method, params => {
events.push({ method, params });
});
});
步骤结束时:
waterfall = await harFromMessages(events);
它适用于导航事件,也适用于 Web 应用程序内部的导航。
但是,我尝试监视的 Web 应用程序具有包含主要内容的 iframe。
我希望在我的瀑布中看到 iframe 请求。
所以几个问题:
- 为什么 Network.responseReceived 或任何其他事件没有捕获此请求?
- 是否可以捕获此类请求?
到目前为止,我已经把 devtool 协议文档都弄红了,没有什么可以用的。
我发现最接近我的问题的是这个问题:
How can I receive events for an embedded iframe using Chrome Devtools Protocol?
我的猜测是,我必须为我可能遇到的每个 iframe 启用网络。
我没有找到任何方法来做到这一点。如果有办法用 devtool 协议来实现,我用 nodsjs 和 puppeteer 来实现它应该没有问题。
感谢您的见解!
编辑 18/08:
在对该主题进行更多搜索后,主要是进程外 iframe,互联网上的很多人都指出了该响应:
https://bugs.chromium.org/p/chromium/issues/detail?id=924937#c13
答案是问题状态:
请注意,最简单的解决方法是 --disable-features 标志。
That said, to work with out-of-process iframes over DevTools protocol,
you need to use Target [1] domain:
- Call Target.setAutoAttach with flatten=true;
- You'll receive Target.attachedToTarget event with a sessionId for the iframe;
- Treat that session as a separate "page" in chrome-remote-interface. Send separate protocol messages with additional sessionId field:
{id: 3, sessionId: "", method: "Runtime.enable", params:
{}}
- You'll get responses and events with the same "sessionId" field which means they are coming from that frame. For example:
{sessionId: "", method: "Runtime.consoleAPICalled",
params: {...}}
但是我还是没能实现。
我正在尝试这个,主要基于木偶操纵者:
const events = [];
const targets = await browser.targets();
const nbTargets = targets.length;
for(var i=0;i<nbTargets;i++){
console.log(targets[i].type());
if (targets[i].type() === 'page') {
client = await targets[i].createCDPSession();
await client.send("Target.setAutoAttach", {
autoAttach: true,
flatten: true,
windowOpen: true,
waitForDebuggerOnStart: false // is set to false in pptr
})
await client.send('Page.enable');
await client.send('Network.enable');
observeTest.forEach(method => {
client.on(method, params => {
events.push({ method, params });
});
});
}
};
但我仍然没有在 iframe 内的 Web 应用程序中获得预期的导航输出。
但是我能够在加载 iframe 的步骤中捕获所有请求。
我想念的是在正确导航之外发生的请求。
有没有人知道将上述 chromium 响应集成到 puppeteer 中?谢谢!
我一直看错了方向。
chrome 网络事件被正确捕获,正如我之前检查“事件”变量时所看到的那样。
问题来自我在 :
上使用的“chrome-har”包
waterfall = await harFromMessages(events);
页面希望页面和 iframe 主事件与请求出现在同一批事件中。否则请求“目前无法映射到任何页面”。
我的场景的步骤有时是同一个 Web 应用程序中的导航(=无导航事件),我没有这些事件并且 chrome-har 无法映射请求,因此发送了一个空的.har
希望它能帮助别人,我搞砸了这个调试...
就上下文而言,我正在使用 Nodejs 和 puppeteer 开发一个综合监控工具。 对于定义场景的每个步骤,我都会捕获屏幕截图、瀑布和性能指标。
我的问题出在瀑布上,我以前使用过 puppeter-har,但这个包无法捕获导航之外的请求。 因此我使用这段代码来捕获所有有趣的请求:
const {harFromMessages} = require('chrome-har');
// Event types to observe for waterfall saving (probably overkill, I just set all events of Page and Network)
const observe = [
'Page.domContentEventFired',
'Page.fileChooserOpened',
'Page.frameAttached',
'Page.frameDetached',
'Page.frameNavigated',
'Page.interstitialHidden',
'Page.interstitialShown',
'Page.javascriptDialogClosed',
'Page.javascriptDialogOpening',
'Page.lifecycleEvent',
'Page.loadEventFired',
'Page.windowOpen',
'Page.frameClearedScheduledNavigation',
'Page.frameScheduledNavigation',
'Page.compilationCacheProduced',
'Page.downloadProgress',
'Page.downloadWillBegin',
'Page.frameRequestedNavigation',
'Page.frameResized',
'Page.frameStartedLoading',
'Page.frameStoppedLoading',
'Page.navigatedWithinDocument',
'Page.screencastFrame',
'Page.screencastVisibilityChanged',
'Network.dataReceived',
'Network.eventSourceMessageReceived',
'Network.loadingFailed',
'Network.loadingFinished',
'Network.requestServedFromCache',
'Network.requestWillBeSent',
'Network.responseReceived',
'Network.webSocketClosed',
'Network.webSocketCreated',
'Network.webSocketFrameError',
'Network.webSocketFrameReceived',
'Network.webSocketFrameSent',
'Network.webSocketHandshakeResponseReceived',
'Network.webSocketWillSendHandshakeRequest',
'Network.requestWillBeSentExtraInfo',
'Network.resourceChangedPriority',
'Network.responseReceivedExtraInfo',
'Network.signedExchangeReceived',
'Network.requestIntercepted'
];
步骤开始时:
// list of events for converting to HAR
const events = [];
client = await page.target().createCDPSession();
await client.send('Page.enable');
await client.send('Network.enable');
observe.forEach(method => {
client.on(method, params => {
events.push({ method, params });
});
});
步骤结束时:
waterfall = await harFromMessages(events);
它适用于导航事件,也适用于 Web 应用程序内部的导航。 但是,我尝试监视的 Web 应用程序具有包含主要内容的 iframe。 我希望在我的瀑布中看到 iframe 请求。
所以几个问题:
- 为什么 Network.responseReceived 或任何其他事件没有捕获此请求?
- 是否可以捕获此类请求?
到目前为止,我已经把 devtool 协议文档都弄红了,没有什么可以用的。 我发现最接近我的问题的是这个问题: How can I receive events for an embedded iframe using Chrome Devtools Protocol?
我的猜测是,我必须为我可能遇到的每个 iframe 启用网络。 我没有找到任何方法来做到这一点。如果有办法用 devtool 协议来实现,我用 nodsjs 和 puppeteer 来实现它应该没有问题。
感谢您的见解!
编辑 18/08:
在对该主题进行更多搜索后,主要是进程外 iframe,互联网上的很多人都指出了该响应: https://bugs.chromium.org/p/chromium/issues/detail?id=924937#c13
答案是问题状态:
请注意,最简单的解决方法是 --disable-features 标志。
That said, to work with out-of-process iframes over DevTools protocol, you need to use Target [1] domain:
- Call Target.setAutoAttach with flatten=true;
- You'll receive Target.attachedToTarget event with a sessionId for the iframe;
- Treat that session as a separate "page" in chrome-remote-interface. Send separate protocol messages with additional sessionId field:
{id: 3, sessionId: "", method: "Runtime.enable", params: {}}- You'll get responses and events with the same "sessionId" field which means they are coming from that frame. For example:
{sessionId: "", method: "Runtime.consoleAPICalled", params: {...}}
但是我还是没能实现。
我正在尝试这个,主要基于木偶操纵者:
const events = [];
const targets = await browser.targets();
const nbTargets = targets.length;
for(var i=0;i<nbTargets;i++){
console.log(targets[i].type());
if (targets[i].type() === 'page') {
client = await targets[i].createCDPSession();
await client.send("Target.setAutoAttach", {
autoAttach: true,
flatten: true,
windowOpen: true,
waitForDebuggerOnStart: false // is set to false in pptr
})
await client.send('Page.enable');
await client.send('Network.enable');
observeTest.forEach(method => {
client.on(method, params => {
events.push({ method, params });
});
});
}
};
但我仍然没有在 iframe 内的 Web 应用程序中获得预期的导航输出。
但是我能够在加载 iframe 的步骤中捕获所有请求。 我想念的是在正确导航之外发生的请求。
有没有人知道将上述 chromium 响应集成到 puppeteer 中?谢谢!
我一直看错了方向。 chrome 网络事件被正确捕获,正如我之前检查“事件”变量时所看到的那样。 问题来自我在 :
上使用的“chrome-har”包waterfall = await harFromMessages(events);
页面希望页面和 iframe 主事件与请求出现在同一批事件中。否则请求“目前无法映射到任何页面”。
我的场景的步骤有时是同一个 Web 应用程序中的导航(=无导航事件),我没有这些事件并且 chrome-har 无法映射请求,因此发送了一个空的.har
希望它能帮助别人,我搞砸了这个调试...