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

如何通过Chrome Debugger的Fetch API修改HTTP响应?

如何通过Chrome Debugger的Fetch API修改HTTP响应?

看起来你已经找对了方向,用Chrome DevTools Protocol的Fetch API确实能实现修改HTTP响应的需求,但你的代码里有几个小问题导致报错,我来帮你梳理并修正:

你的代码里的核心问题

  • 调用Fetch.getResponseBody时参数错误:你漏掉了第一个参数{ tabId },Chrome Debugger的sendCommand方法第一个参数必须是包含tabId的对象,这就是你看到TypeError: Error in invocation of debugger.sendCommand的直接原因。
  • 未限制拦截范围:调用Fetch.enable时没有指定请求匹配规则,会拦截所有请求,既影响性能也容易引发其他问题。
  • 非目标请求处理不当:对于不匹配example.com的请求,没必要去获取响应体再手动填充,直接让请求继续走原始流程更稳妥。
  • 响应头格式问题:fulfillRequest要求响应头是[{name: "...", value: "..."}]格式的数组,直接用params.responseHeaders可能会有格式不兼容的情况。

修正后的完整代码

let tabId;

async function getTabs() {
  return new Promise((resolve) => {
    chrome.tabs.query({}, function (tabs) {
      resolve(tabs);
    });
  });
}

(async () => {
  let tabs = await getTabs();
  let tab = tabs.filter(a => a.url.includes('example.com'))?.[0];
  
  if (!tab) {
    console.log('没有找到包含example.com的标签页');
    return;
  }
  
  tabId = tab.id;

  try {
    await new Promise((resolve, reject) => {
      chrome.debugger.attach({ tabId }, '1.3', (err) => {
        if (err) reject(err);
        else resolve();
      });
    });

    // 只拦截目标域名的请求,减少不必要的拦截
    await new Promise((resolve) => {
      chrome.debugger.sendCommand(
        { tabId },
        'Fetch.enable',
        {
          patterns: [
            { urlPattern: 'https://example.com/*', requestStage: 'Response' }
          ]
        },
        resolve
      );
    });

    chrome.debugger.onEvent.addListener(async (source, method, params) => {
      // 只处理请求暂停的事件,并且确保是当前标签页的事件
      if (source.tabId !== tabId || method !== 'Fetch.requestPaused') return;

      const requestId = params.requestId;
      const isTargetRequest = params.request.url.startsWith('https://example.com/');

      if (isTargetRequest) {
        // 获取原始响应体(注意处理base64编码)
        const responseBodyResult = await new Promise((resolve) => {
          chrome.debugger.sendCommand(
            { tabId },
            'Fetch.getResponseBody',
            { requestId },
            resolve
          );
        });

        // 处理原始响应体的编码,如果是base64就解码,否则直接用
        let originalBody = responseBodyResult.body;
        if (responseBodyResult.base64Encoded) {
          originalBody = atob(originalBody);
        }

        // 替换成自定义内容
        const modifiedBody = 'modified body';
        // 因为fulfillRequest要求body是base64编码的
        const modifiedResponseBody = btoa(modifiedBody);

        // 准备响应头,确保格式正确
        const responseHeaders = params.responseHeaders?.map(header => ({
          name: header.name,
          value: header.value
        })) || [];

        // 填充修改后的响应
        await new Promise((resolve) => {
          chrome.debugger.sendCommand(
            { tabId },
            'Fetch.fulfillRequest',
            {
              requestId,
              responseCode: 200,
              responseHeaders,
              body: modifiedResponseBody,
              base64Encoded: true
            },
            resolve
          );
        });
      } else {
        // 非目标请求,直接继续原始响应流程
        await new Promise((resolve) => {
          chrome.debugger.sendCommand(
            { tabId },
            'Fetch.continueRequest',
            { requestId },
            resolve
          );
        });
      }
    });
  } catch (err) {
    console.error('调试器附加失败:', err);
  }
})();

关键修改说明

  1. 修复了Fetch.getResponseBody的参数:补上了{ tabId }参数,解决了报错问题。
  2. 添加了请求拦截规则:在Fetch.enable时指定了urlPattern,只拦截example.com下的请求,提升效率。
  3. 优化了非目标请求的处理:用Fetch.continueRequest直接让请求走原始流程,避免不必要的响应体处理。
  4. 规范了响应头格式:把原始响应头转换成fulfillRequest要求的数组格式,避免格式错误。
  5. 完善了编码处理:处理了响应体的base64编码和解码,确保修改后的内容能正确显示。
  6. 增加了错误处理:给debugger.attach添加了错误捕获,避免标签页不存在或无法附加时崩溃。

备注:内容来源于stack exchange,提问作者丶 Limeー来夢 丶

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:38:11