如何通过函数调用动态使用declarativeNetRequest的modifyHeaders功能?
如何通过函数调用动态使用declarativeNetRequest的modifyHeaders功能?
嘿,我来帮你解决这个问题!你现在遇到的核心问题是对declarativeNetRequest的工作机制理解有点偏差——它的规则是纯静态的配置结构,根本没法直接在里面写函数或者异步调用,这就是你报错的原因。浏览器会把这些规则编译成高效的内部执行逻辑,只接受字符串、数字这类可序列化的静态值,自定义函数和await调用在规则里完全不被支持。
下面给你两种针对性的解决方案,根据你的实际需求选就行:
方案一:提前计算静态值(适合值不需要每次请求都更新的场景)
如果你的header值不需要每次请求都重新计算,只是初始化的时候动态生成一次,那可以先在规则外部完成异步计算,再把结果塞进规则里:
const MY_CUSTOM_RULE_ID = 1; async function updateDynamicHeaderRule() { // 第一步:先在规则外完成所有异步计算 const rawValue = "my custom header value"; const encoder = new TextEncoder(); const data = encoder.encode(rawValue); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashBase64 = btoa(String.fromCharCode(...hashArray)); // 第二步:用计算好的静态值更新规则 await chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [MY_CUSTOM_RULE_ID], addRules: [ { id: MY_CUSTOM_RULE_ID, priority: 1, action: { type: "modifyHeaders", requestHeaders: [ { operation: "set", header: "my custom name", value: hashBase64 // 直接用提前算好的静态值 } ] }, condition: { resourceTypes: ["main_frame", "sub_frame"] } } ] }); } // 调用函数初始化规则 updateDynamicHeaderRule().catch(err => console.error("更新规则失败:", err));
方案二:实时动态计算(适合每次请求都要生成新值的场景)
如果你的header值需要每次请求都重新计算,那declarativeNetRequest的静态规则就满足不了了,得换成chrome.webRequestAPI——它允许在请求触发的瞬间动态修改headers,完全支持异步操作。
首先要在manifest.json里添加必要的权限:
{ "manifest_version": 3, "background": { "service_worker": "background.js" }, "permissions": ["webRequest", "webRequestBlocking"], "host_permissions": ["<all_urls>"] // 或者指定你需要拦截的具体域名 }
然后在background.js里编写逻辑:
chrome.webRequest.onBeforeSendHeaders.addListener( async (details) => { // 每次请求触发时,实时计算header值 const rawValue = "my custom header value"; const encoder = new TextEncoder(); const data = encoder.encode(rawValue); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashBase64 = btoa(String.fromCharCode(...hashArray)); // 修改请求头:先找有没有同名header,有就替换,没有就新增 const requestHeaders = details.requestHeaders || []; const targetHeaderIndex = requestHeaders.findIndex(h => h.name.toLowerCase() === "my custom name"); if (targetHeaderIndex !== -1) { requestHeaders[targetHeaderIndex].value = hashBase64; } else { requestHeaders.push({ name: "my custom name", value: hashBase64 }); } return { requestHeaders }; }, { urls: ["<all_urls>"], types: ["main_frame", "sub_frame"] }, // 匹配你需要的请求类型和域名 ["blocking", "requestHeaders", "extraHeaders"] // 必须声明blocking权限才能修改请求头 );
再给你理清楚为什么原来的写法报错
你之前把getValue函数和await getValue()直接写在规则的requestHeaders数组里,这完全不符合declarativeNetRequest的规则要求——浏览器解析规则时会把它当成静态JSON结构,根本不认识里面的函数和await关键字,自然会抛出语法错误。这类声明式API的设计初衷就是用静态配置实现高效拦截,不支持嵌入自定义执行逻辑。
备注:内容来源于stack exchange,提问作者Stan
相关产品推荐
相关产品推荐

