Chrome扩展V3迁移:DeclarativeNetRequest改请求头需重载才生效
Chrome扩展V3迁移:DeclarativeNetRequest规则无法在标签导航后立即生效
问题说明
从Chrome扩展V2迁移到V3时,由于WebRequestBlocking被弃用,改用DeclarativeNetRequest拦截并修改出站请求头。需求是表单提交后,拦截当前标签的所有后续出站请求并添加自定义请求头,但目前遇到的问题是:表单提交后标签会导航到新URL,但请求头无法被自动添加,必须强制重载标签才能让规则生效。
已经尝试过的方案:
- 用
chrome.tabs.onUpdated监听标签更新来应用规则 - 添加
chrome.webNavigation.onBeforeNavigate和chrome.webRequest.onBeforeSendHeaders监听器
以上方案都没法在不重载标签的情况下让规则生效。
当前使用的background.ts代码:
// Handle submission of new data chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { const tabId = sender?.tab?.id ?? message.tabId; const tab = await chrome.tabs.get(tabId!); switch (message.type) { case 'submit': const options = await getOptions(); newUrl.searchParams.set('value', message.value); // If the new Url would be the same as the old URL, don't update the tab if (newUrl.toString() === tab.url) { return; } chrome.tabs.update(tabId, {url: newUrl.toString()}, (r) => { console.log('updated tab', r); }); break; case 'log': console.log(`${message.message}:`, message); break; } }); chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { console.log('On Tab Updated'); if (tab.status !== 'loading') { return; } // Get the declarative net request rules for this session const allRules = await chrome.declarativeNetRequest.getSessionRules(); // Get the current rules for this tab const currentRulesForTab = allRules.filter((rule) => { return rule.condition?.tabIds?.includes(tabId); }); if ( condition ) { const newRulesForTab = await getRules(); if (!currentRulesForTab.length) { await chrome.tabs.sendMessage(tabId, { type: 'log', message: 'Initializing session rules for this tab', rules: newRulesForTab }); await chrome.declarativeNetRequest.updateSessionRules({ addRules: newRulesForTab }); // Reload this tab again await chrome.tabs.reload(tabId); } else { if (currentRules !== newRules) { // Send chrome message to this tab to log that the tab is being updated await chrome.tabs.sendMessage(tabId, { type: 'log', message: 'Updating session rules for this tab', rules: newRulesForTab }); await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: currentRulesForTab.map((rule) => rule.id), addRules: newRulesForTab }); // Reload this tab again await chrome.tabs.reload(tabId); } } } else { if (currentRulesForTab.length) { // Send chrome message to this tab to log that the tab is being updated await chrome.tabs.sendMessage(tabId, { type: 'log', message: 'Removing session rules for this tab', rules: currentRulesForTab }); await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: currentRulesForTab.map((rule) => rule.id) }); // Reload this tab again await chrome.tabs.reload(tabId); } } });
问题根源
DeclarativeNetRequest的会话规则(session rules)在标签导航的当前导航周期内不会立即生效——因为发起导航请求时,规则还没被添加或更新,所以这个导航请求以及后续的请求都不会匹配到新规则,必须重载标签开启新的导航周期才能触发规则。
解决方法
方法一:表单提交时提前配置规则,再触发导航
不要等标签更新后才加规则,而是在调用chrome.tabs.update导航之前,先把规则配置好,这样导航请求本身就能被规则匹配到。
修改后的代码:
// Handle submission of new data chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { const tabId = sender?.tab?.id ?? message.tabId; const tab = await chrome.tabs.get(tabId!); switch (message.type) { case 'submit': const options = await getOptions(); // 补充newUrl的初始化(原代码中缺失) const newUrl = new URL(tab.url!); newUrl.searchParams.set('value', message.value); if (newUrl.toString() === tab.url) { return; } // 第一步:提前更新会话规则 const allRules = await chrome.declarativeNetRequest.getSessionRules(); const currentRulesForTab = allRules.filter(rule => rule.condition?.tabIds?.includes(tabId)); const newRulesForTab = await getRules(); // 先移除旧规则(如果存在) if (currentRulesForTab.length) { await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: currentRulesForTab.map(rule => rule.id) }); } // 添加新规则 await chrome.declarativeNetRequest.updateSessionRules({ addRules: newRulesForTab }); // 第二步:触发标签导航 chrome.tabs.update(tabId, { url: newUrl.toString() }, (r) => { console.log('updated tab', r); }); break; case 'log': console.log(`${message.message}:`, message); break; } }); // 保留tabs.onUpdated的规则清理逻辑(无需重载标签) chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (tab.status !== 'loading') return; const allRules = await chrome.declarativeNetRequest.getSessionRules(); const currentRulesForTab = allRules.filter(rule => rule.condition?.tabIds?.includes(tabId)); // 根据你的condition判断是否需要移除规则 if (!condition && currentRulesForTab.length) { await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: currentRulesForTab.map(rule => rule.id) }); } });
方法二:用webNavigation.onBeforeNavigate提前注入规则
如果没法在表单提交时提前处理,可以监听onBeforeNavigate事件——这个事件发生在导航请求发送之前,此时添加规则能确保请求发出前规则已经生效。
修改后的代码:
// 监听导航前事件,提前注入规则 chrome.webNavigation.onBeforeNavigate.addListener(async (details) => { const tabId = details.tabId; // 根据目标URL或其他条件判断是否需要应用规则 if (details.url.includes('你的目标URL匹配规则')) { const allRules = await chrome.declarativeNetRequest.getSessionRules(); const currentRulesForTab = allRules.filter(rule => rule.condition?.tabIds?.includes(tabId)); const newRulesForTab = await getRules(); // 没有规则则添加,规则有变化则更新 if (!currentRulesForTab.length) { await chrome.declarativeNetRequest.updateSessionRules({ addRules: newRulesForTab }); } else if (JSON.stringify(currentRulesForTab) !== JSON.stringify(newRulesForTab)) { await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: currentRulesForTab.map(rule => rule.id), addRules: newRulesForTab }); } } }); // 原有的消息监听逻辑保持不变,移除导航后的重载操作 chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { const tabId = sender?.tab?.id ?? message.tabId; const tab = await chrome.tabs.get(tabId!); switch (message.type) { case 'submit': const options = await getOptions(); const newUrl = new URL(tab.url!); newUrl.searchParams.set('value', message.value); if (newUrl.toString() === tab.url) { return; } chrome.tabs.update(tabId, { url: newUrl.toString() }, (r) => { console.log('updated tab', r); }); break; case 'log': console.log(`${message.message}:`, message); break; } });
注意事项
- 确保规则的
condition里正确设置tabIds,精准绑定目标标签,避免影响其他标签的请求 - 会话规则(session rules)会在浏览器关闭后自动失效,不需要手动持久化
- 尽量避免频繁更新规则,可以通过对比规则内容判断是否需要更新,减少性能开销
内容的提问来源于stack exchange,提问作者Shresth Bhimrajka
相关产品推荐
相关产品推荐

