Electron BrowserWindow не может получить ответ при подключении отладчика

#javascript #electron #google-chrome-devtools #chrome-devtools-protocol

#javascript #electron #google-chrome-devtools #chrome-devtools-протокол

Вопрос:

Я пишу приложение Electron, которое создает BrowserWindow . Я хочу захватить несколько запросов, отправленных на сервер, мне также нужны ответы на запросы. Используя Electron WebRequest api, я не могу получать ответы, поэтому поискал в Интернете и обнаружил, что могу программно подключить отладчик.

Я подключаю отладчик, используя приведенный ниже код, и получаю почти все ответы правильно. Но для одного большего запроса я не могу получить ответ. Я получаю сообщение об ошибке

 Error: No resource with given identifier found
 

Если я запускаю DevTools и перехожу к этому запросу, я также не могу получить ответ: Failed to load response data . Если я прокомментирую приведенный ниже код, ответ в DevTools отобразится правильно.

Обратите внимание, что это происходит только для одного конкретного запроса, который возвращает ответ размером около 1 МБ. Для всех других запросов я могу получить ответ с помощью 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)
            })
        }
    }
});
 

Короткое обновление
Стек событий для этого конкретного запроса выглядит следующим образом, где 13548.212 просто 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

 

Ответ №1:

Похоже, я нашел решение. Это скорее обходной путь, но он работает. Я не использовал Network.getResponseBody . Я использовал Fetch (https://chromedevtools.github.io/devtools-protocol/tot/Fetch ).

Чтобы использовать это, нужно подписаться на ответы, соответствующие шаблону. Затем вы можете реагировать на Fetch.requestPaused события. При этом у вас есть прямой доступ к запросу и косвенный к ответу. Чтобы получить ответ, вызовите Fetch.getResponseBody правильный requestId . Также не забудьте отправить Fetch.continueRequest как

Запрос приостанавливается до тех пор, пока клиент не ответит одним из continueRequest, failRequest или 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})
        }
    });
 

Комментарии:

1. Спасибо! Экспериментальный домен выборки отлично решает мою аналогичную проблему 🙂