【问题标题】:Chrome Extension - How to get HTTP Response Body?Chrome 扩展 - 如何获取 HTTP 响应正文?
【发布时间】:2021-10-07 08:00:45
【问题描述】:

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

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

我还检查了这些 stackoverflows

有没有什么巧妙的方法在 Chrome 扩展中获取 HTTP 响应体?

【问题讨论】:

  • 没有通用的方法。这仅适用于特定用例。

标签: javascript google-chrome-extension


【解决方案1】:

如果有帮助的话,我会展示我完成的代码。我加了下划线来获取请求的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"}

但是我直接在后台devtools中调试,它得到了第二个正确的body。

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 不是完美的解决方案,有人可以提供帮助吗? 谢谢。

【讨论】:

    【解决方案2】:

    现在在 Chrome 开发者工具扩展中有一个方法,示例代码可以在这里看到:blog post

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

    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 打开时才会被激活。
    【解决方案3】:

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

    Chrome extension to read HTTP response

    答案告诉了如何获取响应标题并显示在另一个页面中。但是响应 obj 中没有正文信息(请参阅event-responseReceived)。如果您想在没有其他页面的情况下获得响应body,试试这个。

    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)来关闭丑陋的提示。

    对不起,也许没有帮助... ^ ^

    【讨论】:

    • 使用--silent-debugger-extension-api命令行切换浏览器来消除黄条,必须是浏览器的第一个实例
    • 我用上面的代码做了一个内容脚本,并在响应正文部分添加了一个console.log和alert,但是什么也没发生。代码应该放在哪里?
    • 我收到错误无法“附加”到 chrome://url。无论如何,只附加到特定的网址?
    • 这是从后台脚本还是从内容脚本运行的?
    • @evanjmg 你可以在manifest.json的权限数组中放入“tabs”来查询url。在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)); } }
    【解决方案4】:

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

    第一种方式是:

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

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

    我在博客here.中详细记录了这两种方法

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

    【讨论】:

    • 您的文章没有说明如何将响应发送到后台页面,因为注入 'chrome.runtime.sendMessage' 不起作用。
    • @Andrew 生病检查,这篇文章只是为了阅读响应正文。请问您在哪里使用“chrome.runtime.sendMessage”?
    • 我试图在注入的内容脚本中使用它,但它(显然)不起作用。文章提到“你可以传递给 BG”,所以很高兴知道如何做到这一点。
    • @Andrew 你可以在内容脚本中使用chrome.runtime.sendMessagedeveloper.chrome.com/extensions/content_scripts。可能还有其他问题。
    • 您不能在注入脚本中使用 chrome 消息传递 api,就像文章通过自运行函数注入它一样。该脚本和扩展程序之间没有消息传递。
    猜你喜欢
    • 1970-01-01
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    相关资源
    最近更新 更多