I'm writing a Chrome Extension that can get HTTP response for a site. I try to use debugger for getting response body:
var gCurrentTab; chrome.debugger.onEvent.addListener(function (source, method, params) { if (gCurrentTab.id != source.tabId) { return; } if (method == "Network.loadingFinished") { var tabId = source.tabId; var requestId = params.requestId; chrome.debugger.sendCommand( source, "Network.getResponseBody", {"requestId": requestId}, function (body) { console.log(body); chrome.debugger.detach(source); }); } } ); chrome.webRequest.onBeforeRequest.addListener(function (details) { var url = details.url; if (url.indexOf('/mypage') >= 0) { chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) { gCurrentTab = tabs[0]; chrome.debugger.attach({ tabId: gCurrentTab.id }, "1.0", function () { chrome.debugger.sendCommand({ tabId: gCurrentTab.id }, "Network.enable"); }); }); } }, {urls: []}, ["requestBody", "blocking"]); But I always get
Unchecked runtime.lastError while running debugger.sendCommand: {"code":-32000,"message":"No resource with given identifier found"} at chrome-extension://ikphgobkghdkjkfplgokmapjlbdfeegl/background.js:11:29
error, and the body is undefined.
Does anyone have idea about why this happen? Thanks!
2 Answers
It was because the website sends many responses, and this code will see another request other than I want, then detach the debugger so I can't get the result.
To solve this, just use a single debugger and do not detach it, or only detach when it's safe to.
var gAttached = false; var gRequests = []; var gObjects = []; chrome.debugger.onEvent.addListener(function (source, method, params) { if (method == "Network.requestWillBeSent") { // If we see a url need to be handled, push it into index queue var rUrl = params.request.url; if (getTarget(rUrl) >= 0) { gRequests.push(rUrl); } } if (method == "Network.responseReceived") { // We get its request id here, write it down to object queue var eUrl = params.response.url; var target = getTarget(eUrl); if (target >= 0) { gObjects.push({ requestId: params.requestId, target: target, url: eUrl }); } } if (method == "Network.loadingFinished" && gObjects.length > 0) { // Pop out the request object from both object queue and request queue var requestId = params.requestId; var object = null; for (var o in gObjects) { if (requestId == gObjects[o].requestId) { object = gObjects.splice(o, 1)[0]; break; } } // Usually loadingFinished will be immediately after responseReceived if (object == null) { console.log('Failed!!'); return; } gRequests.splice(gRequests.indexOf(object.url), 1); chrome.debugger.sendCommand( source, "Network.getResponseBody", {"requestId": requestId}, function (response) { if (response) { dispatch(source.tabId, object.target, JSON.parse(response.body)); } else { console.log("Empty response for " + object.url); } // If we don't have any request waiting for response, re-attach debugger // since without this step it will lead to memory leak. if (gRequests.length == 0) { chrome.debugger.detach({ tabId: source.tabId }, function () { chrome.debugger.attach({ tabId: source.tabId }, "1.0", function () { chrome.debugger.sendCommand({ tabId: source.tabId }, "Network.enable"); }); }); } }); } } ); var initialListener = function (details) { if (gAttached) return; // Only need once at the very first request, so block all following requests var tabId = details.tabId; if (tabId > 0) { gAttached = true; chrome.debugger.attach({ tabId: tabId }, "1.0", function () { chrome.debugger.sendCommand({ tabId: tabId }, "Network.enable"); }); // Remove self since the debugger is attached already chrome.webRequest.onBeforeRequest.removeListener(initialListener); } }; // Attach debugger on startup chrome.webRequest.onBeforeRequest.addListener(initialListener, {urls: ["<all_urls>"]}, ["blocking"]); // Filter if the url is what we want function getTarget(url) { for (var i in TARGETS) { var target = TARGETS[i]; if (url.match(target.url)) { return i; } } return -1; } const TARGETS = [ {url: '/path1', desc: 'target1'}, {url: '/path2', desc: 'target2'} ] 2I am facing similar issue. I figured that sendCommand was not executing immediately. I was facing the issue for the requests which are sent before sending "Network.enable" was complete. Try adding completion for
chrome.debugger.sendCommand({ tabId: gCurrentTab.id }, "Network.enable")