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

Chrome插件中拦截并修改XHR响应的实现疑问

Chrome插件修改HTTP响应内容的可行方案

核心思路

页面上下文直接修改响应内容的限制源于responseText等属性的只读特性,必须通过Chrome扩展的后台层API拦截请求、修改响应后再返回给页面,而非在页面注入代码中直接操作。以下是两种适配不同Manifest版本的可行方案:


方案一:Manifest V3(推荐,Chrome主流版本支持)

利用Service Worker的fetch事件拦截请求,修改响应后构造新响应返回。

1. 配置manifest.json

{
  "manifest_version": 3,
  "name": "响应内容修改插件",
  "version": "1.0",
  "permissions": ["scripting"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "service-worker.js"
  }
}

2. 编写Service Worker逻辑(service-worker.js)

self.addEventListener('fetch', (event) => {
  // 匹配需要拦截的请求,可根据URL、资源类型调整规则
  const targetUrls = /\.html$|\.json$/;
  if (targetUrls.test(event.request.url)) {
    event.respondWith(
      fetch(event.request)
        .then(async (originalResponse) => {
          // 克隆原响应,因为响应流仅能读取一次
          const clonedResp = originalResponse.clone();
          let modifiedContent;

          // 根据响应类型处理内容
          if (event.request.url.endsWith('.json')) {
            const jsonData = await clonedResp.json();
            // 修改JSON数据示例:修改某个字段
            jsonData.title = '修改后的标题';
            modifiedContent = JSON.stringify(jsonData);
          } else {
            const htmlText = await clonedResp.text();
            // 修改HTML内容示例:替换文本
            modifiedContent = htmlText.replace('原始文本', '修改后的文本');
          }

          // 构造新响应,保留原响应的状态码、头部信息
          return new Response(modifiedContent, {
            status: originalResponse.status,
            statusText: originalResponse.statusText,
            headers: originalResponse.headers
          });
        })
        .catch((err) => {
          console.error('响应处理失败:', err);
          // 处理失败时 fallback 到原请求
          return fetch(event.request);
        })
    );
  }
});

方案二:Manifest V2(兼容旧版Chrome)

通过chrome.webRequest拦截请求,取消原请求后自行发起请求、修改内容,再将修改后的内容注入页面。

1. 配置manifest.json

{
  "manifest_version": 2,
  "name": "响应内容修改插件",
  "version": "1.0",
  "permissions": ["webRequest", "webRequestBlocking", "tabs", "<all_urls>"],
  "background": {
    "scripts": ["background.js"]
  }
}

2. 编写后台逻辑(background.js)

// 拦截目标请求
chrome.webRequest.onBeforeRequest.addListener(
  (details) => {
    // 仅拦截主文档或指定类型资源,避免无限循环
    if (details.type === 'main_frame' && details.url.includes('.html')) {
      // 取消原请求
      return { cancel: true };
    }
  },
  { urls: ["<all_urls>"] },
  ["blocking"]
);

// 监听标签页加载,注入修改后的内容
chrome.webNavigation.onDOMContentLoaded.addListener(async (details) => {
  if (details.url.includes('.html')) {
    try {
      // 自行发起请求获取原内容
      const response = await fetch(details.url);
      const originalText = await response.text();
      // 修改内容
      const modifiedText = originalText.replace('原始文本', '修改后的文本');
      
      // 注入修改后的内容到页面
      chrome.tabs.executeScript(details.tabId, {
        code: `document.documentElement.innerHTML = \`${modifiedText}\`;`
      });
    } catch (err) {
      console.error('处理失败:', err);
    }
  }
});

注意事项

  • 针对不同类型的响应(如图片、CSS),需调整内容读取和构造方式:图片用blob()读取,修改后用new Response(blob, options)返回;CSS文本直接修改后返回即可。
  • 确保host_permissions包含需要拦截的所有域名,避免权限不足导致请求失败。
  • Manifest V3中Service Worker无法直接访问DOM,所有修改逻辑需在响应流层面完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:48:16