4

I want to get the response for all the requests that happen at my electron app from the main process.

This image shows that the response I want to get would be at the Response tab and not at the Headers tab on Chrome Dev Tools.

I'm -not- using a <webview> tag, I'm using mainWindow.loadURL().


This only returns the headers and some other stuff, but not the response
session.defaultSession.webRequest.onCompleted({ urls: ['*://*/*'] }, function (details, callback) {
     console.log(details);
});

So to retrieve the response I've tried with this:

try {
     mainWindow.webContents.debugger.attach('1.3')
} catch (err) {
     console.log('Debugger attach failed: ', err)
}

mainWindow.webContents.debugger.on('detach', (event, reason) => {
     console.log('Debugger detached due to: ', reason)
});

mainWindow.webContents.debugger.sendCommand('Network.enable');

session.defaultSession.webRequest.onCompleted({ urls: ['*://*/*'] }, function (details, callback) {
     mainWindow.webContents.debugger.sendCommand('Network.getResponseBody', { requestId: details.id.toString() }, function (body, body64) {
          console.log(body);
     });
});

but it outputs

UnhandledPromiseRejectionWarning: Error: No resource with given identifier found
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either
                                  by throwing inside of an async function without a catch block,
                                  or by rejecting a promise which was not handled with .catch(). 
                                  (rejection id: 1)

so I tried with

try {
     mainWindow.webContents.debugger.attach('1.3')
} catch (err) {
     console.log('Debugger attach failed: ', err)
}

mainWindow.webContents.debugger.on('detach', (event, reason) => {
     console.log('Debugger detached due to: ', reason)
});

mainWindow.webContents.debugger.sendCommand('Network.enable');

mainWindow.webContents.debugger.on('message', function(event, method, params, resourceType){
     if (method === 'Network.responseReceived') {
          if (params.type === 'XHR') {
               mainWindow.webContents.debugger.sendCommand('Network.getResponseBody', { requestId: params.requestId }, function (body, body64) {
                    console.log(body);
               });
          }
     }
});

but it outputs the same:

UnhandledPromiseRejectionWarning: Error: No resource with given identifier found
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either
                                  by throwing inside of an async function without a catch block,
                                  or by rejecting a promise which was not handled with .catch(). 
                                  (rejection id: 1)

Any ideas?

Autumn
  • 325
  • 3
  • 13

2 Answers2

5

It's been a while since I wrote that question, and I just found the solution to it. I was mixing the WebRequest API and the Debugger API, which don't share the same id for the requests. I also put a function as an argument, however the sendMessage method returns a promise and does not have a callback function.

Here is an approach using just the Debugger API which works just fine:

try {
  mainWindow.webContents.debugger.attach('1.3');
} catch (err) {
  console.log('Debugger attach failed: ', err);
}

mainWindow.webContents.debugger.on('detach', (event, reason) => {
  console.log('Debugger detached due to: ', reason);
});

mainWindow.webContents.debugger.on('message', (event, method, params) => {
  if (method === 'Network.responseReceived') {
    console.log(params.response.url);
    mainWindow.webContents.debugger.sendCommand('Network.getResponseBody', { requestId: params.requestId }).then(function(response) {
      console.log(response);
    });
  }
})
  
mainWindow.webContents.debugger.sendCommand('Network.enable');

Made using the following examples:

Autumn
  • 325
  • 3
  • 13
1

To intercept response with body (for requests originated from renderer processes) you can you use:

  1. intercepting proxy server (like mitm-proxy or hoxy or you can write it yourself using http, https, http2 or net modules). You can run it in the main process or in some forked child process
  2. browser extension that will intercept all requests in renderer process using chromium extensions API

In our product we use heavily modified hoxy with http2 support. But we are considering to rewrite it from the start and add extension mode for it.

sanperrier
  • 606
  • 5
  • 12
  • Thank you, I ended up using a Chromium Extension that gets the `body` and sends it to the main process using the `express` server – Autumn Aug 12 '20 at 13:58
  • I need something like this but I can't get interception to work. Are you willing to hop out to DM's in discord or something? – vaid Jun 14 '22 at 11:59