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

ServiceWorker上下文获取webRequest请求体遇未知错误,求解决方案

解决方案:拦截Twitter POST请求体的可行方法

我之前也碰到过类似的问题,Twitter的API请求在webRequest API里返回{error: "Unknown error."},主要是因为浏览器的安全限制(比如跨源请求的requestBody读取限制)或者Twitter对请求体的流式处理导致的。下面给你几个经过验证的替代方案:

方案1:用Content Script重写页面的fetch方法

这种方式不需要处理ServiceWorker的冲突,直接在页面上下文拦截请求,可靠性更高:

步骤1:编写Content Script代码

// content-script.js
(function() {
  // 保存原生fetch方法
  const originalFetch = window.fetch;
  
  window.fetch = async function(...args) {
    let request = args[0];
    
    // 处理Request对象或者URL字符串的情况
    if (typeof request === 'string') {
      request = new Request(request, args[1]);
    }
    
    // 目标请求判断
    if (request.method === 'POST' && request.url.includes('/1.1/friendships/create.json')) {
      if (request.body) {
        try {
          // 克隆请求体(因为body是可读流,只能读取一次)
          const clonedBody = request.body.clone();
          
          // 读取为文本格式,根据实际格式选择json()/formData()
          const bodyText = await clonedBody.text();
          console.log('POST请求体内容:', bodyText);
          
          // 如果是表单格式,可进一步解析
          const formData = new URLSearchParams(bodyText);
          console.log('解析后的表单数据:', Object.fromEntries(formData));
        } catch (err) {
          console.error('读取请求体失败:', err);
        }
      }
    }
    
    // 继续执行原生fetch
    return originalFetch.apply(this, args);
  };
})();

步骤2:配置扩展权限

在你的manifest.json里添加必要权限:

{
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://mobile.twitter.com/*"],
      "js": ["content-script.js"],
      "run_at": "document_start" // 确保在页面脚本加载前注入
    }
  ],
  "permissions": ["activeTab"]
}

方案2:注入自定义ServiceWorker拦截FetchEvent

如果你坚持用ServiceWorker方案,需要替换Twitter原有的SW,注意这里需要处理SW的激活逻辑:

步骤1:自定义ServiceWorker代码

// custom-sw.js
self.addEventListener('fetch', (event) => {
  const request = event.request;
  
  if (request.method === 'POST' && request.url.includes('/1.1/friendships/create.json')) {
    // 克隆请求,避免原请求的body被消耗
    const clonedRequest = request.clone();
    
    // 读取请求体,根据实际格式选择解析方式
    clonedRequest.formData()
      .then(formData => {
        console.log('拦截到的表单数据:', formData);
        // 也可以用json()如果是JSON格式:clonedRequest.json()
      })
      .catch(err => console.error('读取请求体出错:', err));
  }
  
  // 继续转发原请求,不影响页面功能
  event.respondWith(fetch(request));
});

// 监听消息,触发SW跳过等待直接激活
self.addEventListener('message', (event) => {
  if (event.data?.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

步骤2:用Content Script注册并替换SW

// sw-injector.js
if ('serviceWorker' in navigator) {
  // 注册自定义SW(注意要通过web_accessible_resources暴露)
  navigator.serviceWorker.register(chrome.runtime.getURL('custom-sw.js'), { scope: '/' })
    .then(registration => {
      // 监听SW更新
      registration.addEventListener('updatefound', () => {
        const newWorker = registration.installing;
        newWorker.addEventListener('statechange', () => {
          if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
            // 发送消息让新SW激活
            registration.waiting?.postMessage({ type: 'SKIP_WAITING' });
            // 刷新页面让新SW接管
            window.location.reload();
          }
        });
      });
    })
    .catch(err => console.error('注册自定义SW失败:', err));
}

步骤3:配置扩展的web_accessible_resources

在manifest.json里添加:

{
  "web_accessible_resources": [
    {
      "resources": ["custom-sw.js"],
      "matches": ["https://mobile.twitter.com/*"]
    }
  ]
}

为什么webRequest方式不可行?

Twitter的API请求可能使用了流式请求体(Streamed Request Body),而浏览器的webRequest API在处理这类请求时无法完整获取body,只能返回通用错误。另外,跨源场景下(虽然api.twitter.com和mobile.twitter.com同属Twitter,但子域不同),浏览器的安全策略也会限制requestBody的读取权限。

内容的提问来源于stack exchange,提问作者r.beer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:05:34