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

如何为webRequest.onBeforeRequest事件动态修改URL过滤规则?

动态更新浏览器扩展的webRequest拦截规则

这个问题我之前也帮人解决过——你踩的坑是浏览器扩展webRequest API的一个典型特性:添加监听器时的urls参数是一次性计算的,之后不管localStorage怎么变,旧的过滤规则都会一直生效。要实现动态更新拦截规则,有两种非常实用的方案,我给你详细拆解下:

方案一:监听localStorage变化,重新注册监听器

核心思路是:当block_urls更新时,先移除旧的监听器,再用新的URL列表重新注册。这样每次规则变化后,新的请求都会用最新的规则判断。

实现代码

// 保存监听器引用,方便后续移除
let currentBlockingListener = null;

function updateBlockingRules() {
  // 先移除旧的监听器(如果存在)
  if (currentBlockingListener) {
    browser.webRequest.onBeforeRequest.removeListener(currentBlockingListener);
  }

  // 读取最新的拦截URL列表
  const rawBlockUrls = localStorage.getItem('block_urls');
  const blockUrls = rawBlockUrls 
    ? JSON.parse(rawBlockUrls)  // 注意:存储时要转成JSON字符串,比如JSON.stringify(["https://example.com/*"])
    : ["https://default/default"];

  // 定义新的拦截逻辑
  function handleRequest(requestDetails) {
    console.log("Blocking: " + requestDetails.url);
    return {cancel: true};
  }

  // 注册新的监听器
  browser.webRequest.onBeforeRequest.addListener(
    handleRequest,
    {urls: blockUrls},
    ["blocking"]
  );

  // 更新监听器引用
  currentBlockingListener = handleRequest;
}

// 初始化加载规则
updateBlockingRules();

// 监听localStorage的外部修改(比如从扩展弹窗修改)
window.addEventListener('storage', (event) => {
  if (event.key === 'block_urls') {
    updateBlockingRules();
  }
});

// 注意:如果是扩展内部脚本修改localStorage,storage事件不会触发,修改后要手动调用updateBlockingRules()
// 示例:localStorage.setItem('block_urls', JSON.stringify(["https://example.com/*"])); updateBlockingRules();

关键注意点

  • 必须确保block_urls在localStorage中是JSON格式的数组字符串,否则JSON.parse会报错;
  • 扩展内部修改localStorage时,storage事件不会触发,需要手动调用更新函数。

方案二:放弃urls过滤,在监听器内动态判断

如果觉得管理监听器的注册/移除太麻烦,可以换个思路:把urls设置成匹配所有请求,然后在每次请求触发时,实时读取localStorage的最新规则,判断是否需要拦截。

实现代码

function handleRequest(requestDetails) {
  // 每次请求都读取最新的拦截规则
  const rawBlockUrls = localStorage.getItem('block_urls');
  const blockUrls = rawBlockUrls 
    ? JSON.parse(rawBlockUrls)
    : ["https://default/default"];

  // 判断当前URL是否匹配拦截规则(用浏览器原生的URLPattern API更可靠)
  const shouldBlock = blockUrls.some(pattern => {
    try {
      const urlPattern = new URLPattern(pattern);
      return urlPattern.test(requestDetails.url);
    } catch (e) {
      console.error("无效的URL规则:", pattern, e);
      return false;
    }
  });

  if (shouldBlock) {
    console.log("Blocking: " + requestDetails.url);
    return {cancel: true};
  }
  // 不拦截则返回undefined,让请求正常进行
}

// 注册监听所有请求的监听器
browser.webRequest.onBeforeRequest.addListener(
  handleRequest,
  {urls: ["<all_urls>"]},
  ["blocking"]
);

优缺点对比

  • 优点:逻辑简单,不需要管理监听器的生命周期,完全实时响应规则变化;
  • 缺点:会监听所有请求,性能上比精准匹配略差,但对于绝大多数扩展场景来说,这个性能差异可以忽略不计。

额外建议

推荐把localStorage换成浏览器扩展专属的browser.storage.local API,它更适合扩展的持久化存储:

  • 支持异步操作,不会阻塞主线程;
  • 内置了browser.storage.onChanged事件,能可靠监听所有规则变化;
  • 存储容量比localStorage更大。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:31:46