webRequest.onBeforeRequest

当请求即将发出且请求头尚不可用时,会触发此事件。如果您想取消或重定向请求,这是一个很好的监听时机。

要取消或重定向请求,首先在 addListener()extraInfoSpec 数组参数中包含 "blocking"。然后,在监听器函数中,返回一个 BlockingResponse 对象,并设置相应的属性。

  • 要取消请求,请包含一个值为 truecancel 属性。
  • 要重定向请求,请包含一个 redirectUrl 属性,其值设置为您要重定向到的 URL。

如果扩展程序想要将公共(例如 HTTPS)URL 重定向到扩展程序页面,则扩展程序的 manifest.json 文件必须包含一个 web_accessible_resources 键,其中列出扩展程序页面的 URL。

当多个阻塞处理程序修改请求时,只有一组修改会生效。重定向和取消具有相同的优先级。因此,如果您取消了一个请求,如果另一个阻塞处理程序重定向了该请求,您可能会再次看到具有相同 requestId 的另一个请求。

从 Firefox 52 开始,监听器可以返回一个解析为 BlockingResponsePromise,而不是直接返回 BlockingResponse。这使得监听器可以异步处理请求。

如果您使用 "blocking",则您的 manifest.json 中必须具有 "webRequestBlocking" API 权限

语法

js
browser.webRequest.onBeforeRequest.addListener(
  listener,             // function
  filter,               //  object
  extraInfoSpec         //  optional array of strings
)
browser.webRequest.onBeforeRequest.removeListener(listener)
browser.webRequest.onBeforeRequest.hasListener(listener)

事件有三个函数

addListener(listener, filter, extraInfoSpec)

向此事件添加监听器。

removeListener(listener)

停止监听此事件。listener 参数是要移除的监听器。

hasListener(listener)

检查 listener 是否已为此事件注册。如果正在监听,则返回 true,否则返回 false

addListener 语法

参数

监听器

当此事件发生时调用的函数。该函数将传递此参数

details

object。有关请求的详细信息。有关更多信息,请参阅 details 部分。

返回: webRequest.BlockingResponse。如果在 extraInfoSpec 参数中指定了 "blocking",则事件监听器应返回一个 BlockingResponse 对象,并可以设置其 cancel 或其 redirectUrl 属性。从 Firefox 52 开始,监听器可以返回一个解析为 BlockingResponsePromise,而不是直接返回 BlockingResponse。这使得监听器可以异步处理请求。

filter

webRequest.RequestFilter。一个过滤器,限制发送给此监听器的事件。

extraInfoSpec 可选

string 数组。事件的额外选项。您可以传递以下任何值

  • "blocking":使请求同步,以便您可以取消或重定向请求
  • "requestBody":将 requestBody 包含在传递给监听器的 details 对象中

额外对象

details

cookieStoreId

string。如果请求来自上下文身份中打开的标签页,则为上下文身份的 cookie 存储 ID。有关更多信息,请参阅使用上下文身份

documentUrl

string。资源将加载到的文档的 URL。例如,如果“https://example.com”上的网页包含图像或 iframe,则图像或 iframe 的 documentUrl 将是“https://example.com”。对于顶级文档,documentUrl 未定义。

frameAncestors

array。包含帧层次结构中每个文档(直至顶级文档)的信息。数组中的第一个元素包含有关所请求文档的直接父级的信息,最后一个元素包含有关顶级文档的信息。如果加载实际上是针对顶级文档,则此数组为空。

url

string。文档加载来源的 URL。

frameId

integer。文档的 frameIddetails.frameAncestors[0].frameIddetails.parentFrameId 相同。

frameId

integer。如果请求发生在主帧中,则为零;正值是请求发生所在子帧的 ID。如果加载了(子)帧的文档(typemain_framesub_frame),frameId 表示此帧的 ID,而不是外部帧的 ID。帧 ID 在一个标签页内是唯一的。

incognito

boolean。请求是否来自隐私浏览窗口。

method(方法)

string。标准 HTTP 方法:例如,“GET”或“POST”。

originUrl

string。触发请求的资源的 URL。例如,如果“https://example.com”包含一个链接,并且用户点击该链接,则生成请求的 originUrl 为“https://example.com”。

originUrl 通常但不总是与 documentUrl 相同。例如,如果一个页面包含一个 iframe,并且 iframe 包含一个将新文档加载到 iframe 中的链接,则生成请求的 documentUrl 将是 iframe 的父文档,但 originUrl 将是包含链接的 iframe 中文档的 URL。

parentFrameId

integer。包含发送请求的帧的父帧的 ID。如果没有父帧,则设置为 -1。

proxyInfo

object。此属性仅在请求通过代理时存在。它包含以下属性:

主机

string。代理服务器的主机名。

port

integer。代理服务器的端口号。

type

string。代理服务器的类型。以下之一:

  • "http":HTTP 代理(或 HTTPS 的 SSL CONNECT)
  • "https":通过 TLS 连接到代理的 HTTP 代理
  • "socks":SOCKS v5 代理
  • "socks4":SOCKS v4 代理
  • "direct":无代理
  • "unknown":未知代理
username

string。代理服务的用户名。

proxyDNS

boolean。如果代理将根据提供的主机名执行域名解析,这意味着客户端不应自行进行 DNS 查找,则为 True。

failoverTimeout

integer。故障转移超时(秒)。如果代理连接失败,在此期间将不再使用该代理。

requestBody 可选

object。包含 HTTP 请求正文数据。仅当 extraInfoSpec 包含 "requestBody" 时才提供。

error 可选

string。如果在获取请求正文数据时遇到任何错误,则会设置此项。

formData 可选

object。如果请求方法是 POST 且正文是 UTF-8 编码为“multipart/form-data”或“application/x-www-form-urlencoded”的键值对序列,则存在此对象。

它是一个字典,其中每个键包含该键的所有值的列表。例如:{'key': ['value1', 'value2']}。如果数据是另一种媒体类型,或者格式错误,则该对象不存在。

raw 可选

webRequest.UploadData 数组。如果请求方法是 PUT 或 POST,并且正文尚未在 formData 中解析,则此数组包含未解析的请求正文元素。

requestId

string。请求的 ID。请求 ID 在浏览器会话中是唯一的,因此您可以使用它们来关联与同一请求相关的不同事件。

tabId

integer。请求发生所在标签页的 ID。如果请求与标签页无关,则设置为 -1。

thirdParty

boolean。指示请求及其内容窗口层次结构是否是第三方。

timeStamp

number。此事件触发的时间,以纪元以来的毫秒数表示。

type

webRequest.ResourceType。正在请求的资源类型:例如,“image”、“script”、“stylesheet”。

url

string。请求的目标。

urlClassification

object。如果请求被Firefox 跟踪保护分类,则与请求关联的跟踪类型。这是一个包含以下属性的对象:

firstParty

array 类型的 string。请求的第一方分类标志。

thirdParty

array 类型的 string。请求或其窗口层次结构的第三方分类标志。

分类标志包括:

  • fingerprintingfingerprinting_content:表示请求涉及指纹识别(“发现指纹识别的来源”)。
    • fingerprinting 表示该域属于指纹识别和跟踪类别。此类域的示例包括希望将配置文件与访问用户关联的广告商。
    • fingerprinting_content 表示该域属于指纹识别类别但不属于跟踪类别。此类域的示例包括使用指纹识别技术识别访问用户以进行反欺诈目的的支付提供商。
  • cryptominingcryptomining_content:类似于指纹识别类别,但用于加密挖矿资源。
  • trackingtracking_adtracking_analyticstracking_socialtracking_content:表示请求涉及跟踪。tracking 是任何通用跟踪请求,adanalyticssocialcontent 后缀标识跟踪器的类型。
  • emailtrackingemailtracking_content:表示请求涉及跟踪电子邮件。
  • any_basic_tracking:一个元标志,结合了跟踪和指纹识别标志,不包括 tracking_contentfingerprinting_content
  • any_strict_tracking:一个元标志,结合了所有跟踪和指纹识别标志。
  • any_social_tracking:一个元标志,结合了所有社交跟踪标志。

您可以在 disconnect.me 网站上找到有关跟踪器类型的更多信息。content 后缀表示跟踪并提供内容的跟踪器。阻止它们可以保护用户,但也可能导致网站损坏或元素无法显示。

使用 BlockingResponse 时的 DNS 解析顺序

关于在 OnBeforeRequest 中使用 BlockingResponse 时的 DNS 解析:在 HTTP 通道中,带有阻塞响应的 onBeforeRequest 确实发生在 DNS 解析之前,也发生在推测性连接之前。对于其他通道,推测性连接可能导致 DNS 请求发生在 onBeforeRequest 之前。这种顺序不是扩展程序开发者应该依赖的,因为它可能因浏览器而异,也可能因浏览器版本而异,更不用说一个请求通道与另一个请求通道之间了。请参阅 Mozilla 开发者提供的关于 DNS 解析顺序的 BugZilla 问题澄清

示例

此代码记录与 <all_urls> 模式匹配的每个请求资源的 URL

js
function logURL(requestDetails) {
  console.log(`Loading: ${requestDetails.url}`);
}

browser.webRequest.onBeforeRequest.addListener(logURL, {
  urls: ["<all_urls>"],
});

此代码取消向“https://mdn.org.cn/”下的 URL 发出的图片请求(要查看效果,请访问 MDN 上包含图片的任何页面,例如 webRequest

js
// match pattern for the URLs to redirect
let pattern = "https://mdn.org.cn/*";

// cancel function returns an object
// which contains a property `cancel` set to `true`
function cancel(requestDetails) {
  console.log(`Canceling: ${requestDetails.url}`);
  return { cancel: true };
}

// add the listener,
// passing the filter argument and "blocking"
browser.webRequest.onBeforeRequest.addListener(
  cancel,
  { urls: [pattern], types: ["image"] },
  ["blocking"],
);

此代码通过重定向替换所有向“https://mdn.org.cn/”下的 URL 发出的图片网络请求(要查看效果,请访问 MDN 上包含图片的任何页面,例如 webRequest

js
// match pattern for the URLs to redirect
let pattern = "https://mdn.org.cn/*";

// redirect function
// returns an object with a property `redirectURL`
// set to the new URL
function redirect(requestDetails) {
  console.log(`Redirecting: ${requestDetails.url}`);
  return {
    redirectUrl:
      "https://38.media.tumblr.com/tumblr_ldbj01lZiP1qe0eclo1_500.gif",
  };
}

// add the listener,
// passing the filter argument and "blocking"
browser.webRequest.onBeforeRequest.addListener(
  redirect,
  { urls: [pattern], types: ["image"] },
  ["blocking"],
);

此代码与上一个示例完全相同,只是监听器异步处理请求。它返回一个 Promise,该 Promise 设置一个计时器,并在计时器到期时解析为重定向 URL

js
// match pattern for the URLs to redirect
let pattern = "https://mdn.org.cn/*";

// URL we will redirect to
let redirectUrl =
  "https://38.media.tumblr.com/tumblr_ldbj01lZiP1qe0eclo1_500.gif";

// redirect function returns a Promise
// which is resolved with the redirect URL when a timer expires
function redirectAsync(requestDetails) {
  console.log(`Redirecting async: ${requestDetails.url}`);
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ redirectUrl });
    }, 2000);
  });
}

// add the listener,
// passing the filter argument and "blocking"
browser.webRequest.onBeforeRequest.addListener(
  redirectAsync,
  { urls: [pattern], types: ["image"] },
  ["blocking"],
);

另一个示例,将所有图片重定向到数据 URL

js
let pattern = "https://mdn.org.cn/*";

let image = `
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
    <rect style="stroke-width: 10; stroke: #666666;" width="100%" height="100%" fill="#d4d0c8" />
    <text transform="translate(0, 9)" x="50%" y="50%" width="100%" fill="#666666" height="100%" style="text-anchor: middle; font: bold 10pt 'Segoe UI', Arial, Helvetica, Sans-serif;">Blocked</text>
  </svg>
`;

function listener(details) {
  const redirectUrl = `data:image/svg+xml,${encodeURIComponent(image)}`;
  return { redirectUrl };
}

browser.webRequest.onBeforeRequest.addListener(
  listener,
  { urls: [pattern], types: ["image"] },
  ["blocking"],
);

这是另一个版本

js
function randomColor() {
  return `#${Math.floor(Math.random() * 16777215).toString(16)}`;
}

const pattern = "https://mdn.org.cn/*";

let image = `
  <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
    <rect width="100%" height="100%" fill="${randomColor()}"/>
  </svg>
`;

function listener(details) {
  const redirectUrl = `data:image/svg+xml,${encodeURIComponent(image)}`;
  return { redirectUrl };
}

browser.webRequest.onBeforeRequest.addListener(
  listener,
  { urls: [pattern], types: ["image"] },
  ["blocking"],
);

扩展程序示例

浏览器兼容性

注意:此 API 基于 Chromium 的 chrome.webRequest API。本文档源自 Chromium 代码中的 web_request.json