#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. Спасибо! Экспериментальный домен выборки отлично решает мою аналогичную проблему 🙂