webRequest.onHeadersReceived

当请求的 HTTP 响应头被接收时触发。使用此事件修改 HTTP 响应头。

要使响应头与请求数据的其余部分一起传递给监听器,请在 extraInfoSpec 数组中传递 "responseHeaders"

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

扩展程序可能会发出冲突的请求。如果两个扩展程序针对同一个请求监听 onHeadersReceived 并返回 responseHeaders 来设置原始响应中不存在的相同头(例如,Set-Cookie),则只有其中一个更改会成功。

但是,Content-Security-Policy 头被区别对待;其值会被组合起来应用所有指定的策略。但如果两个扩展程序设置的 CSP 值冲突,CSP 服务会使限制更严格以解决冲突。例如,如果一个扩展程序设置 img-src: example.com,而另一个扩展程序设置 img-src: example.org,则结果是 img-src: 'none'。合并的修改总是倾向于更严格,尽管扩展程序可以删除原始 CSP 头。

如果你想查看系统处理的头,而没有其他扩展程序更改它们的风险,请使用 webRequest.onResponseStarted,尽管你无法在此事件上修改头。

语法

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

事件有三个函数

addListener(listener, filter, extraInfoSpec)

向此事件添加监听器。

removeListener(listener)

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

hasListener(listener)

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

addListener 语法

参数

监听器

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

details

object。请求的详细信息。如果你在 extraInfoSpec 中包含了 "responseHeaders",这将包含响应头。

返回:webRequest.BlockingResponse。如果在 extraInfoSpec 参数中指定了 "blocking",则事件监听器将返回一个 BlockingResponse 对象,并且可以设置其 responseHeaders 属性。在 Firefox 中,返回值可以是一个解析为 BlockingResponsePromise

filter

webRequest.RequestFilter。一组过滤器,用于限制发送到此监听器的事件。

extraInfoSpec 可选

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

  • "blocking" 使请求同步,以便你可以修改请求和响应头
  • "responseHeaders" 将响应头包含在传递给监听器的 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 在一个标签页内是唯一的。

fromCache

boolean。响应是否从磁盘缓存中获取。

incognito

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

ip

string。发送请求的服务器的 IP 地址。它可能是一个 IPv6 字面地址。

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。故障转移超时(秒)。如果代理连接失败,在此期间将不再使用该代理。

requestId

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

responseHeaders 可选

webRequest.HttpHeaders。此请求接收到的 HTTP 响应头。

statusCode

integer。服务器返回的标准 HTTP 状态码。

statusLine

string。响应的 HTTP 状态行,或 HTTP/0.9 响应(即缺少状态行的响应)的“HTTP/0.9 200 OK”字符串。

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 后缀表示跟踪并提供内容的跟踪器。阻止它们可以保护用户,但也可能导致网站损坏或元素无法显示。

示例

此代码在从目标 URL 请求资源时设置一个额外的 cookie

js
let targetPage =
  "https://mdn.org.cn/en-US/Firefox/Developer_Edition";

// Add the new header to the original array,
// and return it.
function setCookie(e) {
  const setMyCookie = {
    name: "Set-Cookie",
    value: "my-cookie1=my-cookie-value1",
  };
  e.responseHeaders.push(setMyCookie);
  return { responseHeaders: e.responseHeaders };
}

// Listen for onHeaderReceived for the target page.
// Set "blocking" and "responseHeaders".
browser.webRequest.onHeadersReceived.addListener(
  setCookie,
  { urls: [targetPage] },
  ["blocking", "responseHeaders"],
);

此代码执行与上一个示例相同的事情,只是监听器是异步的,返回一个用新头解析的 Promise

js
const targetPage =
  "https://mdn.org.cn/en-US/Firefox/Developer_Edition";

// Return a Promise that sets a timer.
// When the timer fires, resolve the promise with
// modified set of response headers.
function setCookieAsync(e) {
  const asyncSetCookie = new Promise((resolve, reject) => {
    setTimeout(() => {
      const setMyCookie = {
        name: "Set-Cookie",
        value: "my-cookie1=my-cookie-value1",
      };
      e.responseHeaders.push(setMyCookie);
      resolve({ responseHeaders: e.responseHeaders });
    }, 2000);
  });

  return asyncSetCookie;
}

// Listen for onHeaderReceived for the target page.
// Set "blocking" and "responseHeaders".
browser.webRequest.onHeadersReceived.addListener(
  setCookieAsync,
  { urls: [targetPage] },
  ["blocking", "responseHeaders"],
);

浏览器兼容性

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