MV3扩展迁移:如何用declarativeNetRequest替代webRequest修改请求头
MV2 迁移 MV3:请求头条件修改适配方案
核心思路
Manifest V3 中推荐使用 chrome.declarativeNetRequest API 替代 MV2 的 webRequest.onBeforeSendHeaders(blocking 模式在 MV3 中限制较多且性能较差)。针对你需要按 tabId 筛选请求、修改特定请求头的需求,核心是通过动态会话规则绑定指定 tab,并配置请求头修改操作。
步骤1:配置 Manifest 权限
确保 manifest.json 中包含必要权限和声明:
{ "manifest_version": 3, "name": "你的扩展名称", "version": "1.0", "permissions": ["declarativeNetRequest", "tabs"], "host_permissions": ["<all_urls>"], "background": { "service_worker": "background.js" } }
declarativeNetRequest:用于创建网络请求规则tabs:用于监听 tab 关闭事件,清理无效规则host_permissions: ["<all_urls>"]:允许修改所有 URL 的请求头
步骤2:实现动态规则逻辑
在 background.js 中编写代码,实现按 tabId 筛选、修改请求头的逻辑:
// 存储当前生效的规则ID,用于后续移除操作 let activeRuleIds = []; // 生成指定tab的请求头修改规则 function generateTabRules(tabId, userAgent, deviceType) { const rules = []; let baseRuleId = tabId * 10; // 用tabId生成唯一规则ID,避免冲突 // 规则1:修改 User-Agent rules.push({ id: baseRuleId++, priority: 1, action: { type: "modifyHeaders", requestHeaders: [{ header: "User-Agent", operation: "set", value: userAgent }] }, condition: { tabIds: [tabId], urlFilter: "*", resourceTypes: ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"] } }); // 针对 android-phone 设备,添加 sec-ch-ua 系列头规则 if (deviceType === "android-phone") { // 规则2:修改 sec-ch-ua rules.push({ id: baseRuleId++, priority: 1, action: { type: "modifyHeaders", requestHeaders: [{ header: "sec-ch-ua", operation: "set", value: `"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"` }] }, condition: { tabIds: [tabId], urlFilter: "*", resourceTypes: ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"] } }); // 规则3:修改 sec-ch-ua-mobile rules.push({ id: baseRuleId++, priority: 1, action: { type: "modifyHeaders", requestHeaders: [{ header: "sec-ch-ua-mobile", operation: "set", value: "?1" }] }, condition: { tabIds: [tabId], urlFilter: "*", resourceTypes: ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"] } }); // 规则4:修改 sec-ch-ua-platform rules.push({ id: baseRuleId++, priority: 1, action: { type: "modifyHeaders", requestHeaders: [{ header: "sec-ch-ua-platform", operation: "set", value: `"Android"` }] }, condition: { tabIds: [tabId], urlFilter: "*", resourceTypes: ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"] } }); } return rules; } // 为单个tab应用规则 function applyTabRules(tabId) { // 假设 edit 是你的全局配置对象,确保在 service worker 中可访问 const userAgent = edit.userAgent; const deviceType = edit.device; // 先移除该tab之前的规则(如果存在) const oldTabRules = activeRuleIds.filter(id => Math.floor(id / 10) === tabId); if (oldTabRules.length > 0) { chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: oldTabRules }); activeRuleIds = activeRuleIds.filter(id => !oldTabRules.includes(id)); } // 添加新规则 const newRules = generateTabRules(tabId, userAgent, deviceType); const newRuleIds = newRules.map(r => r.id); chrome.declarativeNetRequest.updateDynamicRules({ addRules: newRules }); activeRuleIds.push(...newRuleIds); } // 批量更新目标tab的规则(对应原MV2中的Tabs数组) function updateAllTargetTabs(targetTabIds) { // 清空所有旧规则 if (activeRuleIds.length > 0) { chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: activeRuleIds }); activeRuleIds = []; } // 为每个目标tab应用规则 targetTabIds.forEach(tabId => applyTabRules(tabId)); } // 监听tab关闭事件,自动清理对应规则 chrome.tabs.onRemoved.addListener(tabId => { const rulesToRemove = activeRuleIds.filter(id => Math.floor(id / 10) === tabId); if (rulesToRemove.length > 0) { chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: rulesToRemove }); activeRuleIds = activeRuleIds.filter(id => !rulesToRemove.includes(id)); } });
关键说明
- tabId 绑定:通过规则的
condition.tabIds字段直接指定规则生效的tab,替代原MV2中手动判断tabId的逻辑,更高效。 - 动态规则管理:使用
updateDynamicRules动态添加/移除规则,适配tab列表或配置(userAgent、deviceType)的变化。 - 规则ID唯一性:用
tabId * 10作为规则ID的基础,确保每个tab的规则ID不冲突。 - 资源类型覆盖:明确指定
resourceTypes包含所有需要修改请求头的资源类型,避免遗漏子资源请求。
内容的提问来源于stack exchange,提问作者user12345678
相关产品推荐
相关产品推荐

