I have a page which communicates to a server every 10 seconds via XHR inside an iframe. I would like to monitor the responses (text/plain UTF-8).
Opposite to the DevTools Network list, it seems Puppeteer does not "detect" XHR responses from inside iframes, with it's normal page procedure:
page.on('response', async (response) => {}
When the ID of the iframe is known, is there any way to receive the XHR responses of the iframe? (with a JS web worker doing the XHR requests)
I have written this example which showcases that requests are indeed captured
from inner frames of your page
. You have to be careful, requests that fail won't actually trigger page.on('response')
handler but will trigger page.on('requestfailed')
.
Also make sure to call await page.setRequestInterception(true)
before adding any request related handlers to your page!
Here is a working example: (it will only trigger requestFailed
due to cross origin restrictions.)
var puppeteer = require('puppeteer')
function simulateRequest() {
function doXmlHTTPRequest() {
function reqListener() {
console.log('xml done.')
console.log(this.responseText);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "https://www.google.com");
oReq.send();
}
setInterval(doXmlHTTPRequest, 2 * 1000)
}
// Easiest way to get an Iframe is by its name.
const findFrame = (frames, name) => {
return frames.find(f => f.name() === name)
}
const main = async() => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage()
// have a page with only an iframe.
const pageContent = '<iframe id="myFrame" name="frameName">'
await page.setContent(pageContent)
// important call!
await page.setRequestInterception(true)
page.on('response', async(res) => {
console.log('Page response received..', )
})
page.on('requestfailed', () => {
console.log('requestfailed recieved')
})
page.on('request', async(res) => {
console.log('page request received..', )
// make sure to continue request.
res.continue()
})
// find the iframe!
const targetFrame = findFrame(page.frames(), 'frameName')
// set some test content..
await targetFrame.setContent('<h1>hello</h1>')
// add a script to iframe which simulates requests!
await targetFrame.addScriptTag({
// execute the function immediatly..
content: `(${simulateRequest.toString()})()`
})
}
main()