问题描述
我正在编写一个创建 browserWindow
的 Electron 应用程序。我想捕获一些发送到服务器的请求,我还希望对那里的请求进行响应。使用 Electron WebRequest
api 无法获得响应,因此在网上搜索并发现我可以通过编程方式附加调试器。
我使用以下代码附加调试器,几乎所有响应都正确。但是对于一个更大的请求,我无法得到响应。我收到一个错误
Error: No resource with given identifier found
如果我启动 DevTools 并导航到该请求,我也无法获得响应:Failed to load response data
。如果我注释掉下面的代码,DevTools 中的响应就会正确显示。
请注意,这仅适用于一个特定请求,它返回大约 1MB 的响应。对于所有其他请求,我可以使用 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
解决方法
看来我找到了解决方案。这是一种解决方法,但它有效。我没有使用 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})
}
});