2

I'm writing an Electron app which creates a BrowserWindow. I want to capture a few requests sent to a server, I also want responses for there requests. Using Electron WebRequest api I can't get responses, so searched the web and found that I can attach a debugger programatically.

I attach debugger using the below code and I get almost all responses correctly. But for one bigger request I can't get the response. I get an error

Error: No resource with given identifier found

If I launch DevTools and navigate to that request I also can't get the response: Failed to load response data. If I comment out below code the response in DevTools show correctly.

Note that this happens only for one specific request which returns about 1MB response. For all other requests I can get the response using getResponseData().

const dbg = win.webContents.debugger

var getResponseData = async (reqId) => {
    const res = await dbg.sendCommand("Network.getResponseBody", {requestId: reqId});
    return res.body
}

try {
    dbg.attach('1.3')
    dbg.sendCommand('Network.enable')
} catch (err) {
    console.log('Debugger attach failed : ', err)
}

dbg.on('detach', async (event, reason) => {
    console.log('Debugger detached due to : ', reason)
})

dbg.on('message', (e, m, p) => {
    if (m === 'Network.requestWillBeSent') {
        if (p.request.url === someURL) {
            const j = JSON.parse(p.request.postData)
            console.log("req " + p.requestId)
            global.webReqs[p.requestId] = { reqData: j}
        }
    } else if (m === 'Network.loadingFinished') {
        if (p.requestId in global.webReqs) {
            console.log("res " + p.requestId)
            getResponseData(p.requestId).then(res => {
                console.log(res.slice(0,60))
            }).catch(err => {
                console.error(err)
            })
        }
    }
});

Short update The event stack for this particular request is as follows, where 13548.212 is simply requestId

Network.requestWillBeSentExtraInfo 13548.212
Network.requestWillBeSent 13548.212
Network.responseReceivedExtraInfo 13548.212
Network.responseReceived 13548.212
Network.dataReceived 13548.212 [repeated 135 times]
...
Network.loadingFinished 13548.212

maklimcz
  • 51
  • 6

1 Answers1

3

Looks that I found a solution. It's rather a workaround, but it works. I didn't use Network.getResponseBody. I used Fetch(https://chromedevtools.github.io/devtools-protocol/tot/Fetch).

To use that one need to subscribe for Responses matching a pattern. Then you can react on Fetch.requestPaused events. During that you have direct access to a request and indirect to a response. To get the response call Fetch.getResponseBody with proper requestId. Also remember to send Fetch.continueRequest as

The request is paused until the client responds with one of continueRequest, failRequest or fulfillRequest

https://chromedevtools.github.io/devtools-protocol/tot/Fetch/#event-requestPaused

   dbg.sendCommand('Fetch.enable', {
            patterns: [
                { urlPattern: interestingURLpattern, requestStage: "Response" }
            ]})

   var getResponseJson = async (requestId) => {
         const res = await dbg.sendCommand("Fetch.getResponseBody", {requestId: requestId})
         return JSON.parse(res.base64Encoded ? Buffer.from(res.body, 'base64').toString() : res.body)
     }
    dbg.on('message', (e, m, p) => {
        if(m === 'Fetch.requestPaused') {
            var reqJson = JSON.parse(p.request.postData)
            var resJson = await getResponseJson(p.requestId)
            ...

            await dbg.sendCommand("Fetch.continueRequest", {requestId: p.requestId})
        }
    });
maklimcz
  • 51
  • 6