Chrome 调试器 Network.getResponseBody 即使在等待 Network.loadingFinished 事件后也会给出“未找到具有给定标识符的资源”

问题描述 投票:0回答:1

我正在编写一个从浏览器游戏获取数据的扩展。它使用 chrome 调试器库来附加调试器,并接收选项卡为服务器获取的每条消息的事件。我查找来自我需要的 URL 的 Network.responseReceived 事件。然后,我等待共享相同 requestId 的 Network.loadingFinished 事件。我使用 requestId 作为参数发送 Network.getResponseBody 命令,该命令为我提供了我处理和存储的请求正文。

问题是,最近,我在请求响应正文时会随机收到错误:{“code”:-32000,“message”:“没有找到具有给定标识符的资源”},我不知道为什么。有时有效,有时无效。

我尝试过的事情:

  • 在 Network.finishedLoading 事件之前发送 Network.getResponseBody
  • 收到finishedLoading事件后立即发送命令
  • 如果失败,则以指数增加的延迟重复发送命令
  • 以不同的静态延迟发送命令

无论我做什么,大约 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 条消息。这是我成功的交换和我收到错误的交换的屏幕截图:

screenshot of messages for a successful request and failed request

每行都有消息类型、收到的时间戳以及消息链的responseID。

另请注意:对于成功的请求,Network.responseReceived 消息的“hasExtraInfo”字段设置为 true,而不成功的请求的 Network.responseReceived 消息则将其设置为 false

如果在 Network.requestWillBeSent 事件触发后收到 Network.enable 命令,Network.getResponseBody 是否总是会失败?我认为只要您拥有该请求的有效responseID,它就可以工作。

javascript google-chrome-extension google-chrome-devtools
1个回答
0
投票

我忘记了我问过这个问题,但我在发布后不久就找到了答案,所以我想如果有人遇到同样的问题,我会把它放在这里。

事实证明,如果在触发 Network.requestWillBeSent 事件时未连接调试器或未启用网络,则 chrome 将不允许您访问响应。

这意味着访问请求正文的唯一方法是在触发 Network.requestWillBeSent 事件之前启用调试器和网络。如果您从链中稍后的事件获取请求 ID 并不重要,如果您的扩展程序错过了第一个事件,chrome 仍然会阻止对响应正文的访问。

当选项卡导航到我正在跟踪的域(而不仅仅是页面路径)时,我能够通过让调试器动态附加和分离来解决该问题。在附加调试器并启用网络之前,等待页面路径不会给我足够的时间来捕获第一个 Network.requestWillBeSent 事件。

© www.soinside.com 2019 - 2024. All rights reserved.