【问题标题】:How to log fetched network resources in JavaScript?如何在 JavaScript 中记录获取的网络资源?
【发布时间】:2013-01-04 01:03:42
【问题描述】:

有没有办法访问浏览器请求的资源列表(在这个 Chrome 检查器的网络面板中找到的资源)?

我希望能够遍历这些获取的资源以显示已访问的域,例如:

for (var i = 0; i < window.navigator.resources.length; i++) {
  var resource = window.navigator.resources[i];
  console.log(resource); //=> e.g. `{domain: "www.google-analytics.com", name: "ga.js"}`
}

或者,也许有一些事件要为其编写处理程序,例如:

window.navigator.onrequest = function(resource) {
  console.log(resource); //=> e.g. `{domain: "www.google-analytics.com", name: "ga.js"}`
}

它不需要跨浏览器工作,甚至可以使用客户端 JavaScript。只要能够以任何方式 访问这些信息就可以了(也许有某种方法可以使用 phantomjs 或从 shell/node 脚本监视网络流量)。有什么想法吗?

【问题讨论】:

    标签: javascript node.js networking google-chrome-extension


    【解决方案1】:

    您可以这样做,但您需要使用 Chrome 扩展程序。

    Chrome 扩展程序具有很多沙盒式的安全性。 Chrome 扩展程序和网页之间的通信是一个多步骤的过程。这是我能提供的最简洁的解释,最后附有一个完整的工作示例:

    1. Chrome 扩展程序可以完全访问 chrome.* API,但 Chrome 扩展程序不能直接与网页 JS 通信,网页 JS 也不能直接与 Chrome 扩展程序通信.

    2. 要弥合 Chrome 扩展程序和网页之间的差距,您需要使用 content script 。内容脚本本质上是在目标网页的window 范围内注入的 JavaScript。内容脚本不能调用函数,也不能访问由网页 JS 创建的变量,但它们确实共享对同一个 DOM 的访问权,因此也共享事件。

    3. 因为不允许直接访问变量和调用函数,所以网页和内容脚本通信的唯一方式是通过触发自定义事件

    例如,如果我想将消息从 Chrome 扩展程序传递到页面,我可以这样做:

    content_script.js

    document.getElementById("theButton").addEventListener("click", function() {
        window.postMessage({ type: "TO_PAGE", text: "Hello from the extension!" }, "*");
    }, false);
    

    web_page.js

    window.addEventListener("message", function(event) {
        // We only accept messages from ourselves
        if (event.source != window)
          return;
    
        if (event.data.type && (event.data.type == "TO_PAGE")) {
          alert("Received from the content script: " + event.data.text);
        }
    }, false);
    

    `4.现在您可以从内容脚本向网页发送消息,您现在需要 Chrome 扩展程序收集您想要的所有网络信息。您可以通过几个不同的模块来完成此操作,但最简单的选项是 webRequest 模块(请参阅下面的 background.js)。

    `5.使用message passing 将网络请求的信息传递到内容脚本,然后传递到网页 JavaScript。

    在视觉上,你可以这样想:

    完整的工作示例:

    前三个文件构成您的 Google Chrome 扩展程序,最后一个文件是您应该上传到某处 http:// 网络空间的 HTML 文件。

    icon.png

    使用任何 16x16 PNG 文件。

    ma​​nifest.json

    {
      "name": "webRequest Logging",
      "description": "Displays the network log on the web page",
      "version": "0.1",
      "permissions": [
        "tabs",
        "debugger",
        "webRequest",
        "http://*/*"
      ],
      "background": {
        "scripts": ["background.js"]
      },
      "browser_action": {
        "default_icon": "icon.png",
        "default_title": "webRequest Logging"
      },
       "content_scripts": [
        {
          "matches": ["http://*/*"],
          "js": ["content_script.js"]
        }
      ],
      "manifest_version": 2
    }
    

    background.js

    var aNetworkLog = [];
    
    chrome.webRequest.onCompleted.addListener(function(oCompleted) {
                var sCompleted = JSON.stringify(oCompleted);
                aNetworkLog.push(sCompleted);
            }
            ,{urls: ["http://*/*"]}
     );
    
    chrome.extension.onConnect.addListener(function (port) {
        port.onMessage.addListener(function (message) {
            if (message.action == "getNetworkLog") {
                port.postMessage(aNetworkLog);
            }
        });
    });
    

    content_script.js

    var port = chrome.extension.connect({name:'test'});
    
    document.getElementById("theButton").addEventListener("click", function() {
    
        port.postMessage({action:"getNetworkLog"});
    
    }, false);
    
    port.onMessage.addListener(function(msg) {
      document.getElementById('outputDiv').innerHTML = JSON.stringify(msg);
    });
    

    并为网页使用以下内容(随便命名):

    <!doctype html>
    <html>
    <head>
        <title>webRequest Log</title>
    </head>
    <body>
        <input type="button" value="Retrieve webRequest Log" id="theButton">
        <div id="outputDiv"></div>
    </head>
    </html>
    

    【讨论】:

    • 大多数人使用debugger API,这是一些新的 +1 :)
    【解决方案2】:

    向@Elliot B 致敬。

    我基本上使用了他所做的,但我希望在内容脚本中触发事件,而不是在后台触发侦听器。无论出于何种原因,我无法从后台脚本连接到端口,所以这就是我想出的。

    PS:你需要扩展文件夹中的 jquery.js 来完成这项工作。

    manifest.json

    {
      "manifest_version": 2,
    
      "name": "MNC",
      "version": "0.0.1",
      "description": "Monitor Network Comms",
      "permissions":["webRequest","*://*/"],
      "content_scripts": [{
      "matches": ["<all_urls>"],
      "run_at": "document_start",
      "js": ["content.js",
            "jquery.js"]
      }],
      "background": {
        "scripts": ["background.js"]
      }
    }
    

    background.js

    var aNetworkLog = [];
    
    chrome.webRequest.onResponseStarted.addListener(
      function(oCompleted) {
        var sCompleted = JSON.stringify(oCompleted);
        aNetworkLog.push(sCompleted);
      },{urls: ["https://*/*"]}
    );
    
    chrome.extension.onConnect.addListener(function (port) {
      chrome.webRequest.onResponseStarted.addListener(
        function(){
          port.postMessage({networkLog:JSON.stringify(aNetworkLog)});
        },{urls: ["https://*/*"]}
      );
      port.onMessage.addListener(function (message) {
        if (message.disconnect==true) {
          port.disconnect();
        }
      });
    });
    

    content.js

    div = $('<div id="outputDiv" style="float:left;max-width:fit-content;position:fixed;display:none;"></div>').appendTo(document.body);
    var port = chrome.extension.connect({name:'networkLogging'});
    port.onMessage.addListener(function (message) {
      if (message.networkLog) {
        div[0].innerHTML = message.networkLog;
      }
    });
    observer = new WebKitMutationObserver(function(mutation,observer){
      JSON.parse(mutation[0]['target'].innerHTML).forEach(function(item){
        JSON.parse(item);
      })
    });
    observer.observe(div[0],{childList:true});
    

    这绝对不是最有效的做事方式,但它对我有用。以为我会在这里添加它以防万一有人需要它。

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 2022-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多