You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展中拦截fetch()无法捕获全部请求的问题求助

Chrome扩展Fetch拦截漏请求的排查与修复方案

可能的漏请求原因

  • 页面预加载脚本提前捕获了原始fetch引用:部分页面会通过预加载机制,在你的注入脚本执行前就保存了fetch的原始引用,后续调用时直接使用该引用绕过重写逻辑。
  • fetch重写实现存在漏洞:未覆盖所有调用场景(如this绑定、非标准参数传递),或未正确代理返回的Promise,导致部分请求未被拦截。
  • 跨帧消息传递丢失:postMessage可能被页面安全策略拦截,或消息监听逻辑存在遗漏,导致请求信息未被接收。
  • 动态加载脚本未被覆盖:页面通过eval、动态<script>标签加载的脚本,可能直接引用原始fetch,未使用重写后的版本。

针对性修复方案

1. 确保注入脚本优先执行

除了在manifest中设置"run_at": "document_start"和"all_frames": true,还需利用世界隔离特性将脚本注入到页面脚本所在的MAIN世界,确保重写的fetch覆盖所有页面脚本:

  • Manifest V3 配置示例:
"content_scripts": [
  {
    "matches": ["<all_urls>"],
    "js": ["content_script.js"],
    "run_at": "document_start",
    "all_frames": true,
    "world": "MAIN"
  }
]
  • 注入脚本时设置同步加载,避免被页面脚本插队:
// content_script.js 中注入inject.js的逻辑
function injectScript() {
  const script = document.createElement('script');
  script.src = chrome.runtime.getURL('inject.js');
  script.async = false; // 同步执行,确保优先覆盖fetch
  document.documentElement.appendChild(script);
  script.remove();
}
injectScript();

2. 正确重写fetch方法

重写时需完全代理原始方法,处理this绑定、所有参数、返回的Promise,并克隆响应避免流被消耗:

// inject.js
const originalFetch = window.fetch;
window.fetch = async function(...args) {
  // 捕获请求信息
  const requestInfo = args[0];
  const requestInit = args[1] || {};
  const requestDetails = {
    url: typeof requestInfo === 'string' ? requestInfo : requestInfo.url,
    method: requestInit.method || 'GET',
    headers: Object.fromEntries(requestInit.headers || new Headers()),
    body: requestInit.body ? await new Response(requestInit.body).text() : null
  };
  // 发送请求信息到content_script
  window.postMessage({ type: 'FETCH_REQUEST', data: requestDetails }, '*');

  // 调用原始fetch并处理响应
  const response = await originalFetch.apply(this, args);
  const clonedResponse = response.clone(); // 克隆响应避免流被消耗
  const responseDetails = {
    url: response.url,
    status: response.status,
    statusText: response.statusText,
    headers: Object.fromEntries(response.headers),
    body: await clonedResponse.text()
  };
  // 发送响应信息
  window.postMessage({ type: 'FETCH_RESPONSE', data: responseDetails }, '*');

  return response;
};

3. 加固消息监听逻辑

在content_script.js中验证消息来源,避免遗漏或接收恶意消息:

// content_script.js
window.addEventListener('message', (event) => {
  // 仅接收当前页面的消息
  if (event.source !== window) return;
  switch(event.data.type) {
    case 'FETCH_REQUEST':
      console.log('捕获fetch请求:', event.data.data);
      // 可转发到background.js做后续处理
      chrome.runtime.sendMessage({ type: 'LOG_FETCH_REQUEST', data: event.data.data });
      break;
    case 'FETCH_RESPONSE':
      console.log('捕获fetch响应:', event.data.data);
      break;
  }
});

4. 补充浏览器层面拦截(推荐)

如果重写fetch仍有遗漏,可结合Chrome扩展的declarativeNetRequest API,从浏览器层面拦截所有网络请求:

  • Manifest V3 配置示例:
"permissions": ["declarativeNetRequest"],
"host_permissions": ["<all_urls>"],
"declarative_net_request": {
  "rule_resources": [
    {
      "id": "fetch_intercept_rules",
      "enabled": true,
      "path": "rules.json"
    }
  ]
}
  • rules.json示例(拦截并记录所有fetch/XHR请求):
[
  {
    "id": 1,
    "priority": 1,
    "action": { "type": "log" },
    "condition": {
      "urlFilter": "*",
      "resourceTypes": ["xmlhttprequest", "fetch"]
    }
  }
]

内容的提问来源于stack exchange,提问作者surya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:15:33