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

qeeaahzv  于 2023-02-21  发布在  Java
关注(0)|答案(5)|浏览(584)

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

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

我还检查了这些堆栈溢出

有什么聪明的方法可以在Chrome扩展中获得HTTP响应主体吗?

fdbelqdn

fdbelqdn1#

我找不到比这个答案更好的方法了。
Chrome extension to read HTTP response
答案告诉我们如何获取响应头并显示在另一个页面中。但是在响应对象中没有正文信息(请参阅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)来关闭这个丑陋的提示。
对不起,也许没什么用......

imzjd6km

imzjd6km2#

现在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.
      }
    }
  });
});
omqzjyyz

omqzjyyz3#

这绝对是Chrome扩展生态系统没有提供的开箱即用的东西。但是,我可以找到几种方法来绕过这个问题,但都有自己的一套缺点。

第一种方法是:

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

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

我已经在一篇博客文章here.中详细记录了这两种方法
如果你遇到任何问题,请告诉我

jdg4fx2g

jdg4fx2g4#

要获得XHR响应主体,可以按照this answer中的说明进行操作。
要获取FETCH响应主体,您可以在this articlethis answer中选中Solution 3。这两种方法都可以在不使用chrome.debugger的情况下获取响应主体。**
简而言之,您需要使用与XHR请求相同的方法将以下函数从内容脚本注入到页面中。

const constantMock = window.fetch;
 window.fetch = function() {
    return new Promise((resolve, reject) => {
        constantMock.apply(this, arguments)
            .then((response) => {
                if (response) {
                    response.clone().json() //the response body is a readablestream, which can only be read once. That's why we make a clone here and work with the clone
                    .then( (json) => {
                        console.log(json);
                        //Do whatever you want with the json
                        resolve(response);
                    })
                    .catch((error) => {
                        console.log(error);
                        reject(response);
                    })
                }
                else {
                    console.log(arguments);
                    console.log('Undefined Response!');
                    reject(response);
                }
            })
            .catch((error) => {
                console.log(error);
                reject(response);
            })
    })
}

如果response.clone().json()不起作用,您可以尝试response.clone().text()

b4qexyjb

b4qexyjb5#

我显示我完成的代码,如果它可以是一些帮助。我添加了下划线,以获得请求的网址,谢谢

//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中有一个bug。如果我有两个URI相同但参数不同的请求。例如:

第二个不会得到正确的响应正文,它将显示:

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

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

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)
    
}

我认为设置超时不是完美的解决方案,有人能给予帮助吗?谢谢。

相关问题