我正在编写一个从浏览器游戏获取数据的扩展。它使用 chrome 调试器库来附加调试器,并接收选项卡为服务器获取的每条消息的事件。我查找来自我需要的 URL 的 Network.responseReceived 事件。然后,我等待共享相同 requestId 的 Network.loadingFinished 事件。我使用 requestId 作为参数发送 Network.getResponseBody 命令,该命令为我提供了我处理和存储的请求正文。
问题是,最近,我在请求响应正文时会随机收到错误:{“code”:-32000,“message”:“没有找到具有给定标识符的资源”},我不知道为什么。有时有效,有时无效。
我尝试过的事情:
无论我做什么,大约 50% 的情况下会失败并显示 -32000 代码,而 50% 的情况下会成功。我总能得到正确的requestId。这是我使用的代码。
const maxRetryAttempts = 5;
// Gets the response body of the requestId in params.requestId
async function GetRewardResponseBody(debuggeeId, params, responseReceivedEpoch) {
var errorArray = [];
var initialDelayMS = 5;
var fetchSucceeded = false;
for(let retryAttempts = 1; retryAttempts <= maxRetryAttempts; retryAttempts++){
await sendCommandPromise(debuggeeId.tabId, params)
.then((response) => {
ProcessRewardJSON(debuggeeId.tabId, response); // Processes data if I didn't get error -32000
console.log("Successfully exiting with debugeeId: ", debuggeeId);
fetchSucceeded = true;
}).catch((error) => { // Error occured
errorArray.push(error);
});
if (fetchSucceeded){break;} // Breaks from for loop so it doesn't re-request
await delay(initialDelayMS); // waits until next attempt
initialDelayMS *= 2;
}
if (!fetchSucceeded){
console.log(errorArray); // Prints all errors to the console
}
console.log("Clearing timeout and returning");
clearTimeout(debuggerTimeout); // Removes timeout that would auto remove the debugger
RemoveDebugger(debuggeeId, false);
}
function sendCommandPromise(tabId, params) {
return new Promise((resolve, reject) => {
try{
chrome.debugger.sendCommand(
{"tabId" : tabId
}, "Network.getResponseBody", {
"requestId": params.requestId
}, function(response) {
if (chrome.runtime.lastError){ // Error -32000 was thrown
reject(chrome.runtime.lastError);
}
else if (!response || !response.body) { // response body was empty for some reason
console.error("Response was empty");
reject(new Error("Response was empty"));
}
else {resolve(response);}
});
}
catch(ex){ // Any other errors
console.log("Error fetching resource");
reject(ex)
}
});
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
---编辑--- 我查看了从游戏中收到的消息,发现每次我无法获取响应正文并最终出现错误 -32000 时,我都会丢失交换的前 3 条消息。这是我成功的交换和我收到错误的交换的屏幕截图:
每行都有消息类型、收到的时间戳以及消息链的responseID。
另请注意:对于成功的请求,Network.responseReceived 消息的“hasExtraInfo”字段设置为 true,而不成功的请求的 Network.responseReceived 消息则将其设置为 false
如果在 Network.requestWillBeSent 事件触发后收到 Network.enable 命令,Network.getResponseBody 是否总是会失败?我认为只要您拥有该请求的有效responseID,它就可以工作。
我忘记了我问过这个问题,但我在发布后不久就找到了答案,所以我想如果有人遇到同样的问题,我会把它放在这里。
事实证明,如果在触发 Network.requestWillBeSent 事件时未连接调试器或未启用网络,则 chrome 将不允许您访问响应。
这意味着访问请求正文的唯一方法是在触发 Network.requestWillBeSent 事件之前启用调试器和网络。如果您从链中稍后的事件获取请求 ID 并不重要,如果您的扩展程序错过了第一个事件,chrome 仍然会阻止对响应正文的访问。
当选项卡导航到我正在跟踪的域(而不仅仅是页面路径)时,我能够通过让调试器动态附加和分离来解决该问题。在附加调试器并启用网络之前,等待页面路径不会给我足够的时间来捕获第一个 Network.requestWillBeSent 事件。