Chrome 扩展 - 如何获取 HTTP 响应正文?

IT技术 javascript google-chrome-extension
2021-02-05 14:38:56

这似乎是一个难题(或不可能??)。我想在观看 Chrome 扩展程序后台脚本的情况下获取并阅读由浏览器中的 HTTP 请求引起的 HTTP 响应。我们可以通过这种方式获取HTTP Request Body

chrome.webRequest.onBeforeRequest.addListener(function(data){
    // data contains request_body
},{'urls':[]},['requestBody']);

我还检查了这些 stackoverflows

有没有什么聪明的方法可以在 Chrome 扩展中获取 HTTP 响应正文?

4个回答

我找不到比这个 anwser 更好的方法了。

用于读取 HTTP 响应的 Chrome 扩展程序

答案告诉了如何获取 响应头并显示在另一个页面中。但响应对象中没有正文信息(请参阅event-responseReceived)。如果您想在 没有其他页面的情况下获得响应正文,请尝试此操作。

var currentTab;
var version = "1.0";

chrome.tabs.query( //get current Tab
    {
        currentWindow: true,
        active: true
    },
    function(tabArray) {
        currentTab = tabArray[0];
        chrome.debugger.attach({ //debug at current tab
            tabId: currentTab.id
        }, version, onAttach.bind(null, currentTab.id));
    }
)


function onAttach(tabId) {

    chrome.debugger.sendCommand({ //first enable the Network
        tabId: tabId
    }, "Network.enable");

    chrome.debugger.onEvent.addListener(allEventHandler);

}


function allEventHandler(debuggeeId, message, params) {

    if (currentTab.id != debuggeeId.tabId) {
        return;
    }

    if (message == "Network.responseReceived") { //response return 
        chrome.debugger.sendCommand({
            tabId: debuggeeId.tabId
        }, "Network.getResponseBody", {
            "requestId": params.requestId
        }, function(response) {
            // you get the response body here!
            // you can close the debugger tips by:
            chrome.debugger.detach(debuggeeId);
        });
    }

}

我认为它对我来说已经足够有用了,你可以用它chrome.debugger.detach(debuggeeId)来关闭丑陋的提示。

抱歉,可能没有帮助... ^ ^

这是从后台脚本运行还是从内容脚本运行?
2021-03-13 14:38:56
我从上面的代码制作了一个内容脚本,并在响应正文部分添加了一个 console.log 和警报,但没有任何反应。代码应该放在哪里?
2021-03-17 14:38:56
我收到错误无法“附加”到 chrome://url。无论如何围绕这个并且只附加到特定的网址?
2021-03-21 14:38:56
@evanjmg 如果将“tabs”放入manifest.json. chrome.tabs.query,使用function (tabArray) { currentTab = tabArray[0]; if(!currentTab.url.startsWith("chrome:")){ chrome.debugger.attach({ //debug at current tab tabId: currentTab.id }, version, onAttach.bind(null, currentTab.id)); } }
2021-03-31 14:38:56
使用--silent-debugger-extension-api命令行切换到午餐浏览器去掉黄色条,它必须是浏览器的第一个实例
2021-04-02 14:38:56

现在在 Chrome 开发者工具扩展中有一种方法,示例代码可以在这里看到:博客文章

简而言之,这是对他的示例代码的改编:

chrome.devtools.network.onRequestFinished.addListener(request => {
  request.getContent((body) => {
    if (request.request && request.request.url) {
      if (request.request.url.includes('facebook.com')) {

         //continue with custom code
         var bodyObj = JSON.parse(body);//etc.
      }
}
});
});
来自文章本身:这种方法的缺点是我们必须始终保持 Chrome DevTools 打开,因为 DevTools 扩展仅在 DevTools 打开时激活。
2021-04-01 14:38:56

这绝对不是 Chrome 扩展生态系统开箱即用的。但是,我可以找到几种方法来解决这个问题,但这两种方法都有自己的缺点。

一种方式是:

  1. 使用内容脚本注入我们自己的自定义脚本。
  2. 使用自定义脚本扩展 XHR 的本机方法以读取响应。
  3. 将响应添加到隐藏(非display: none)元素内的网页 DOM
  4. 使用内容脚本读取隐藏的响应。

第二种方法是创建一个DevTools扩展其是,提供了一个API来读取每个请求的唯一扩展。

我已在此处的博客文章中详细记录了这两种方法

如果您遇到任何问题,请告诉我!:)

您不能像文章使用自运行功能注入脚本那样在注入的脚本中使用 chrome 消息传递 API。该脚本和扩展程序之间没有消息传递。
2021-03-16 14:38:56
@Andrew 您可以chrome.runtime.sendMessage在内容脚本中使用:developer.chrome.com/extensions/content_scripts可能是其他地方出了问题。
2021-03-23 14:38:56
您的文章没有说明如何向后台页面发送响应,因为注入 'chrome.runtime.sendMessage' 不起作用。
2021-04-01 14:38:56
@Andrew 不好检查,这篇文章只是为了阅读响应正文。请问你在哪里使用'chrome.runtime.sendMessage'?
2021-04-04 14:38:56
我试图在注入的内容脚本中使用它,但它(显然)不起作用。文章提到“你可以传递给 BG”,所以知道如何做到这一点会很好。
2021-04-09 14:38:56

如果有帮助,我会展示我完成的代码。我添加了下划线来获取请求 url,谢谢

//background.js
import _, { map } from 'underscore';

var currentTab;
var version = "1.0";

chrome.tabs.onActivated.addListener(activeTab => {
    currentTab&&chrome.debugger.detach({tabId:currentTab.tabId});
    currentTab = activeTab;
    chrome.debugger.attach({ //debug at current tab
        tabId: currentTab.tabId
    }, version, onAttach.bind(null, currentTab.tabId));
});

function onAttach(tabId) {
    chrome.debugger.sendCommand({ //first enable the Network
        tabId: tabId
    }, "Network.enable");
    chrome.debugger.onEvent.addListener(allEventHandler);
}

function allEventHandler(debuggeeId, message, params) {
    if (currentTab.tabId !== debuggeeId.tabId) {
        return;
    }
    if (message === "Network.responseReceived") { //response return
        chrome.debugger.sendCommand({
            tabId: debuggeeId.tabId
        }, "Network.getResponseBody", {
            "requestId": params.requestId
            //use underscore to add callback a more argument, passing params down to callback
        }, _.partial(function(response,params) {
            // you get the response body here!
            console.log(response.body,params.response.url);
            // you can close the debugger tips by:
            // chrome.debugger.detach(debuggeeId);
        },_,params));
    }
}

我还发现 chrome.debugger.sendCommand 中有一个错误。如果我有两个具有相同 URI 但参数不同的请求。如:

第二个不会得到更正的 responseBody,它会显示:

Chrome Extension: "Unchecked runtime.lastError: {"code":-32000,"message":"No resource with given identifier found"}

但是我直接在后台开发工具中调试,它得到了第二个正确的主体。

chrome.debugger.sendCommand({tabId:2},"Network.getResponseBody",{requestId:"6932.574"},function(response){console.log(response.body)})

所以tabId和requestId没有问题。然后我用 setTimeout 包装 chrome.debugger.sendCommand,它将正确获得第一个和第二个 responseBody。

if (message === "Network.responseReceived") { //response return            
console.log(params.response.url,debuggeeId.tabId,params.requestId)
        setTimeout(()=>{
            chrome.debugger.sendCommand({
                tabId: debuggeeId.tabId
            }, "Network.getResponseBody", {
                "requestId": params.requestId
                //use underscore to add callback a more argument, passing params down to callback
            }, _.partial(function(response,params,debuggeeId) {
                // you get the response body here!
                console.log(response.body,params.response.url);
                // you can close the debugger tips by:
                // chrome.debugger.detach(debuggeeId);
            },_,params,debuggeeId));
        },800)
    
}

我认为 setTimeout 不是完美的解决方案,有人可以提供帮助吗?谢谢。