说明
chrome.declarativeNetRequest API 用于通过指定声明性规则来屏蔽或修改网络请求。这样一来,扩展程序就可以在不拦截网络请求和查看其内容的情况下修改网络请求,从而提供更高的隐私保护。
权限
declarativeNetRequestdeclarativeNetRequestWithHostAccess“declarativeNetRequest”和“declarativeNetRequestWithHostAccess”权限提供相同的功能。它们之间的区别在于何时请求或授予权限。
"declarativeNetRequest"- 在安装时触发权限警告,但提供对
allow、allowAllRequests和block规则的隐式访问权限。请尽可能使用此权限,以免需要向主持人请求完全访问权限。 "declarativeNetRequestFeedback"- 为未封装的扩展程序启用调试功能,具体而言是
getMatchedRules()和onRuleMatchedDebug。 "declarativeNetRequestWithHostAccess"- 安装时不会显示权限警告,但您必须先请求主机权限,然后才能对主机执行任何操作。如果您想在已具有主机权限的扩展程序中使用声明性网络请求规则,而不生成额外的警告,则此设置非常适合。
可用性
清单
除了前面所述的权限之外,某些类型的规则集(尤其是静态规则集)还需要声明 "declarative_net_request" 清单键,该键应是一个包含单个键(名为 "rule_resources")的字典。此键是一个包含 Ruleset 类型字典的数组,如下所示。(请注意,由于“Ruleset”只是一个数组,因此不会显示在清单的 JSON 中。)本文档后面部分介绍了静态规则集。
{
"name": "My extension",
...
"declarative_net_request" : {
"rule_resources" : [{
"id": "ruleset_1",
"enabled": true,
"path": "rules_1.json"
}, {
"id": "ruleset_2",
"enabled": false,
"path": "rules_2.json"
}]
},
"permissions": [
"declarativeNetRequest",
"declarativeNetRequestFeedback"
],
"host_permissions": [
"http://www.blogger.com/*",
"http://*.google.com/*"
],
...
}
规则和规则集
如需使用此 API,请指定一个或多个规则集。规则集包含一个规则数组。单个规则可执行以下操作之一:
- 屏蔽网络请求。
- 升级架构(从 http 到 https)。
- 通过否定任何匹配的已屏蔽规则,防止请求被屏蔽。
- 重定向网络请求。
- 修改请求或响应标头。
规则集有三种类型,管理方式略有不同。
- 动态
- 可在浏览器会话和扩展程序升级期间保持不变,并且在扩展程序使用期间通过 JavaScript 进行管理。
- 会话
- 在浏览器关闭时以及安装新版本的扩展程序时清除。在使用扩展程序时,会话规则通过 JavaScript 进行管理。
- 静态
- 在安装或升级扩展程序时进行打包、安装和更新。静态规则存储在 JSON 格式的规则文件中,并在清单文件中列出。
动态规则集和会话级范围的规则集
在使用扩展程序时,动态规则集和会话规则集通过 JavaScript 进行管理。
- 动态规则在浏览器会话和扩展程序升级期间保持不变。
- 浏览器关闭时以及安装新版本的扩展程序时,会清除会话规则。
每种规则集类型只有一个。扩展程序可以通过调用 updateDynamicRules() 和 updateSessionRules() 动态添加或移除规则,前提是未超出规则限制。如需了解规则限制,请参阅规则限制。您可以在代码示例下查看相关示例。
静态规则集
与动态规则和会话规则不同,静态规则在安装或升级扩展程序时进行打包、安装和更新。它们以 JSON 格式存储在规则文件中,并使用 "declarative_net_request" 和 "rule_resources" 键(如上所述)以及一个或多个 Ruleset 字典指示给扩展程序。Ruleset 字典包含规则文件的路径、文件中包含的规则集的 ID,以及规则集是启用还是停用。当您以编程方式启用或停用规则集时,后两个属性非常重要。
{
...
"declarative_net_request" : {
"rule_resources" : [{
"id": "ruleset_1",
"enabled": true,
"path": "rules_1.json"
},
...
]
}
...
}
如需测试规则文件,请以未打包的形式加载扩展程序。有关无效静态规则的错误和警告仅针对未打包的扩展程序显示。系统会忽略打包扩展程序中的无效静态规则。
加急审核
对静态规则集的更改可能符合快速审核条件。请参阅符合条件的更改的加急审核。
启用和停用静态规则和规则集
在运行时,您可以启用或停用单个静态规则和完整的静态规则集。
已启用的静态规则和规则集的集合会在浏览器会话之间保持不变。这两者都不会在扩展程序更新后保留,这意味着只有您选择保留在规则文件中的规则会在更新后可用。
出于性能方面的原因,一次可启用的规则和规则集数量也有限制。调用 getAvailableStaticRuleCount() 以检查可启用的额外规则数量。如需了解规则限制,请参阅规则限制。
如需启用或停用静态规则,请调用 updateStaticRules()。此方法接受一个 UpdateStaticRulesOptions 对象,其中包含要启用或停用的规则 ID 数组。ID 使用 Ruleset 字典的 "id" 键进行定义。停用的静态规则数量上限为 5,000 条。
如需启用或停用静态规则集,请调用 updateEnabledRulesets()。此方法接受一个 UpdateRulesetOptions 对象,其中包含要启用或停用的规则集 ID 数组。ID 使用 Ruleset 字典的 "id" 键进行定义。
构建规则
无论规则类型如何,规则都以四个字段开头,如下所示。虽然 "id" 和 "priority" 键采用的是数字,但 "action" 和 "condition" 键可以提供多个屏蔽和重定向条件。以下规则会屏蔽从 "foo.com" 发送到任何包含 "abc" 作为子字符串的网址的所有脚本请求。
{
"id" : 1,
"priority": 1,
"action" : { "type" : "block" },
"condition" : {
"urlFilter" : "abc",
"initiatorDomains" : ["foo.com"],
"resourceTypes" : ["script"]
}
}
网址匹配
Declarative Net Request 能够使用模式匹配语法或正则表达式来匹配网址。
网址过滤条件语法
规则的 "condition" 键允许使用 "urlFilter" 键来处理指定网域下的网址。您可以使用模式匹配令牌创建模式。以下是一些示例。
urlFilter |
组合 | 不匹配 |
|---|---|---|
"abc" |
https://abcd.com https://example.com/abcd |
https://ab.com |
"abc*d" |
https://abcd.com https://example.com/abcxyzd |
https://abc.com |
"||a.example.com" |
https://a.example.com/ https://b.a.example.com/xyz https://a.example.company |
https://example.com/ |
"|https*" |
https://example.com | http://example.com/ http://https.com |
"example*^123|" |
https://example.com/123 http://abc.com/example?123 |
https://example.com/1234 https://abc.com/example0123 |
正则表达式
条件也可以使用正则表达式。请参阅 "regexFilter" 键。如需了解适用于这些条件的限制,请参阅使用正则表达式的规则。
撰写优质的网址条件
编写规则时,请务必确保规则始终与整个网域匹配。否则,您的规则可能会在意外情况下匹配。例如,使用模式匹配语法时:
google.com错误地与https://example.com/?param=google.com匹配||google.com错误地与https://google.company匹配https://www.google.com错误地与https://example.com/?param=https://www.google.com匹配
建议使用:
||google.com/,用于匹配所有路径和所有子网域。|https://www.google.com/,用于匹配所有路径,但不匹配任何子网域。
同样,您可以使用 ^ 和 / 字符来锚定正则表达式。例如,^https:\/\/www\.google\.com\/ 与 https://www.google.com 上的任何路径匹配。
规则评估
浏览器会在网络请求生命周期的各个阶段应用 DNR 规则。
在请求之前
在发出请求之前,扩展程序可以使用匹配的规则来阻止或重定向(包括将方案从 HTTP 升级到 HTTPS)该请求。
对于每个扩展程序,浏览器都会确定一个匹配规则列表。此处未包含具有 modifyHeaders 操作的规则,因为这些规则将在稍后处理。此外,具有 responseHeaders 条件的规则将在稍后(当响应标头可用时)考虑,因此不包含在内。
然后,对于每个扩展程序,Chrome 会为每个请求选择最多一个候选广告。Chrome 会按优先级对所有匹配的规则进行排序,然后找到匹配的规则。优先级相同的规则按操作排序(allow 或 allowAllRequests > block > upgradeScheme > redirect)。
如果候选规则是 allow 或 allowAllRequests 规则,或者发出请求的框架之前已匹配到此扩展程序中优先级更高或相同的 allowAllRequests 规则,则该请求会被“允许”,并且扩展程序不会对该请求产生任何影响。
如果有多个扩展程序想要阻止或重定向此请求,系统会选择要采取的单个操作。Chrome 会按 block > redirect 或 upgradeScheme > allow 或 allowAllRequests 的顺序对规则进行排序。如果两个规则属于同一类型,Chrome 会选择来自最近安装的扩展程序的规则。
在发送请求标头之前
在 Chrome 将请求标头发送到服务器之前,系统会根据匹配的 modifyHeaders 规则更新标头。
在单个扩展程序中,Chrome 会通过查找所有匹配的 modifyHeaders 规则来构建要执行的修改列表。与之前类似,只有优先级高于任何匹配的 allow 或 allowAllRequests 规则的规则才会包含在内。
Chrome 会按一定顺序应用这些规则,以便始终先评估最近安装的扩展程序的规则,然后再评估较旧的扩展程序的规则。此外,一个扩展程序中优先级较高的规则始终会先于同一扩展程序中优先级较低的规则应用。值得注意的是,即使在扩展程序之间:
- 如果某条规则附加到某个标头,则优先级较低的规则只能附加到该标头。不允许执行设置和移除操作。
- 如果某条规则设置了标头,则只有来自同一扩展程序的优先级较低的规则才能附加到该标头。不允许进行其他修改。
- 如果某条规则移除了某个标头,则优先级较低的规则无法进一步修改该标头。
收到回答后
收到响应标头后,Chrome 会评估具有 responseHeaders 条件的规则。
在按 action 和 priority 对这些规则进行排序并排除因匹配的 allow 或 allowAllRequests 规则而变得冗余的任何规则(此过程与“请求之前”中的步骤完全相同)后,Chrome 可能会代表扩展程序阻止或重定向请求。
请注意,如果请求到达此阶段,则表示该请求已发送到服务器,并且服务器已收到请求正文等数据。具有响应标头条件的屏蔽或重定向规则仍会运行,但实际上无法屏蔽或重定向请求。
对于屏蔽规则,发出请求的网页会收到屏蔽响应,并且 Chrome 会提前终止请求,从而处理这种情况。对于重定向规则,Chrome 会向重定向的网址发出新请求。请务必考虑这些行为是否符合您扩展程序的隐私权预期。
如果请求未被阻止或重定向,Chrome 会应用所有 modifyHeaders 规则。对响应标头应用修改的方式与“在发送请求标头之前”中所述的方式相同。由于请求已发出,因此对请求标头应用修改不会产生任何影响。
安全规则
安全规则是指操作为 block、allow、allowAllRequests 或 upgradeScheme 的规则。这些规则受动态规则配额增加的限制。
规则限制
在浏览器中加载和评估规则会产生性能开销,因此使用该 API 时会受到一些限制。限制取决于您使用的规则类型。
静态规则
静态规则是指在清单文件中声明的规则文件中指定的规则。扩展程序最多可以在 "rule_resources" 清单键中指定 100 个静态规则集,但一次只能启用其中的 50 个规则集。后者称为 MAX_NUMBER_OF_ENABLED_STATIC_RULESETS。这些规则集总共至少包含 30,000 条规则。这称为 GUARANTEED_MINIMUM_STATIC_RULES。
之后可用的规则数量取决于用户浏览器上安装的所有扩展程序启用的规则数量。您可以在运行时通过调用 getAvailableStaticRuleCount() 找到此数字。您可以在代码示例下查看相关示例。
会话规则
一个扩展程序最多可以有 5,000 条会话规则。这以 MAX_NUMBER_OF_SESSION_RULES 的形式公开。
在 Chrome 120 之前,动态规则和会话规则的总数上限为 5, 000。
动态规则
扩展程序可以至少有 5,000 条动态规则。这以 MAX_NUMBER_OF_UNSAFE_DYNAMIC_RULES 的形式公开。
从 Chrome 121 开始,安全动态规则(以 MAX_NUMBER_OF_DYNAMIC_RULES 形式公开)的上限增加到 30,000 条。在 5,000 条规则的限制范围内添加的任何不安全规则也会计入此限制。
在 Chrome 120 之前,动态规则和会话规则的总数上限为 5, 000。
使用正则表达式的规则
所有类型的规则都可以使用正则表达式;不过,每种类型的正则表达式规则总数不得超过 1000 条。这称为 MAX_NUMBER_OF_REGEX_RULES。
此外,每条规则在编译后的大小必须小于 2KB。这与规则的复杂程度大致相关。如果您尝试加载超出此限制的规则,系统会显示类似如下的警告,并忽略该规则。
rules_1.json: Rule with id 1 specified a more complex regex than allowed
as part of the "regexFilter" key.
与 Service Worker 的互动
declarativeNetRequest 仅适用于到达网络堆栈的请求。这包括来自 HTTP 缓存的响应,但不包括通过 Service Worker 的 onfetch 处理程序的响应。declarativeNetRequest 不会影响由 Service Worker 生成的响应或从 CacheStorage 检索的响应,但会影响在 Service Worker 中对 fetch() 的调用。
可通过网络访问的资源
declarativeNetRequest 规则无法将公开资源请求重定向到无法通过网络访问的资源。这样做会触发错误。即使指定的 Web 可访问资源归重定向扩展程序所有,也是如此。如需为 declarativeNetRequest 声明资源,请使用清单的 "web_accessible_resources" 数组。
标头修改
仅支持对以下请求标头执行附加操作:accept、accept-encoding、accept-language、access-control-request-headers、cache-control、connection、content-language、cookie、forwarded、if-match、if-none-match、keep-alive、range、te、trailer、transfer-encoding、upgrade、user-agent、via、want-digest、x-forwarded-for。此许可名单区分大小写(bug 449152902)。
在附加到请求或响应标头时,浏览器会尽可能使用适当的分隔符。
示例
代码示例
更新动态规则
以下示例展示了如何调用 updateDynamicRules()。updateSessionRules() 的流程相同。
// Get arrays containing new and old rules
const newRules = await getNewRules();
const oldRules = await browser.declarativeNetRequest.getDynamicRules();
const oldRuleIds = oldRules.map(rule => rule.id);
// Use the arrays to update the dynamic rules
await browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: oldRuleIds,
addRules: newRules
});
更新静态规则集
以下示例展示了如何在考虑可用静态规则集数量和已启用静态规则集数量上限的情况下启用和停用规则集。当您需要的静态规则数量超出允许的数量时,可以这样做。为此,您应安装部分规则集,并停用部分规则集(在清单文件中将 "Enabled" 设置为 false)。
async function updateStaticRules(enableRulesetIds, disableCandidateIds) {
// Create the options structure for the call to updateEnabledRulesets()
let options = { enableRulesetIds: enableRulesetIds }
// Get the number of enabled static rules
const enabledStaticCount = await browser.declarativeNetRequest.getEnabledRulesets();
// Compare rule counts to determine if anything needs to be disabled so that
// new rules can be enabled
const proposedCount = enableRulesetIds.length;
if (enabledStaticCount + proposedCount > browser.declarativeNetRequest.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS) {
options.disableRulesetIds = disableCandidateIds
}
// Update the enabled static rules
await browser.declarativeNetRequest.updateEnabledRulesets(options);
}
规则示例
以下示例说明了 Chrome 如何确定扩展程序中规则的优先级。在查看这些规则时,您可能需要在单独的窗口中打开优先级规则。
“priority”键
这些示例需要 host 权限才能访问 *://*.example.com/*。
如需确定特定网址的优先级,请查看(开发者定义的)"priority" 键、"action" 键和 "urlFilter" 键。以下示例引用了下方显示的示例规则文件。
- 导航到 https://google.com
- 有两条规则涵盖此网址:ID 为 1 和 4 的规则。ID 为 1 的规则会生效,因为
"block"操作的优先级高于"redirect"操作。其余规则不适用,因为它们适用于更长的网址。 - 导航到 https://google.com/1234
- 由于网址变长,ID 为 2 的规则现在也匹配了,而不仅仅是 ID 为 1 和 4 的规则。ID 为 2 的规则适用,因为
"allow"的优先级高于"block"和"redirect"。 - 导航到 https://google.com/12345
- 所有这四条规则都与此网址匹配。ID 为 3 的规则适用,因为其开发者定义的优先级是该组中最高的。
[
{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": {"urlFilter": "||google.com/", "resourceTypes": ["main_frame"] }
},
{
"id":