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

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

这似乎是一个难题(或者不可能??)。 我想在观看 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
5个回答
42
投票

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

用于读取 HTTP 响应的 Chrome 扩展

答案告诉我们如何获取响应标题并显示在另一个页面中。但是响应对象中没有正文信息(请参阅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)
来关闭丑陋的提示。

抱歉,也许没有帮助... ^ ^


17
投票

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

13
投票

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

第一种方法是:

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

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

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

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


10
投票
要获得 XHR

response 正文,您可以按照此答案中的说明进行操作。

要获取 FETCH

response 正文,您可以检查本文中的解决方案 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()


2
投票
如果有帮助的话,我会展示我完成的代码。我添加了下划线来获取请求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 但参数不同的请求。如:

    请求 1:
  • https://www.example.com/orders-api/search?limit=15&offer=0
  • 请求2:
  • https://www.example.com/orders-api/search?limit=85&offer=15
第二个不会得到修正后的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 不是完美的解决方案,有人可以提供帮助吗?
谢谢。

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