拦截 HTTP 请求

要拦截 HTTP 请求,请使用 webRequest API。此 API 使您能够为 HTTP 请求的不同阶段添加侦听器。在侦听器中,您可以

  • 访问请求头和主体以及响应头。
  • 取消和重定向请求。
  • 修改请求和响应头。

本文介绍了 webRequest 模块的三个不同用法

  • 在发出请求时记录请求 URL。
  • 重定向请求。
  • 修改请求头。

记录请求 URL

要了解如何使用 webRequest 记录请求,请创建一个名为“requests”的新目录。在此目录中,创建一个名为“manifest.json”的文件并添加

json
{
  "description": "Demonstrating webRequests",
  "manifest_version": 2,
  "name": "webRequest-demo",
  "version": "1.0",

  "permissions": ["webRequest", "<all_urls>"],

  "background": {
    "scripts": ["background.js"]
  }
}

接下来,创建一个名为“background.js”的文件并添加

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

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

您使用 onBeforeRequest 在开始请求之前调用 logURL() 函数。logURL() 函数从事件对象中获取请求的 URL 并将其记录到浏览器控制台。{urls: ["<all_urls>"]} 模式 表示您拦截对所有 URL 的 HTTP 请求。

进行测试

在浏览器控制台中,您应该会看到浏览器请求的任何资源的 URL。例如,此屏幕截图显示了加载维基百科页面时的 URL

Browser console menu: URLs from extension

重定向请求

现在使用 webRequest 重定向 HTTP 请求。首先,将“manifest.json”替换为此

json
{
  "description": "Demonstrating webRequests",
  "manifest_version": 2,
  "name": "webRequest-demo",
  "version": "1.0",

  "permissions": [
    "webRequest",
    "webRequestBlocking",
    "https://mdn.org.cn/"
  ],

  "background": {
    "scripts": ["background.js"]
  }
}

此处的更改

  • 添加 webRequestBlocking 权限。当扩展程序想要修改请求时,需要此额外权限。
  • <all_urls> 权限替换为单个 主机权限,因为这是最佳实践,可以最大程度地减少请求的权限数量。

接下来,将“background.js”替换为此

js
let pattern = "https://mdn.org.cn/*";
const targetUrl =
  "https://mdn.org.cn/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_second_WebExtension/frog.jpg";

function redirect(requestDetails) {
  console.log(`Redirecting: ${requestDetails.url}`);
  if (requestDetails.url === targetUrl) {
    return;
  }
  return {
    redirectUrl: targetUrl,
  };
}

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

同样,您使用 onBeforeRequest 事件侦听器在每次发出请求之前运行函数。此函数将 redirectUrl 替换为函数中指定的目标 URL。在本例中,来自 第二个扩展教程 的青蛙图像。

这次您没有拦截每个请求:{urls:[pattern], types:["image"]} 选项指定您仅拦截 (1) 位于“https://mdn.org.cn/”下的 URL 和 (2) 图像资源的请求。有关更多信息,请参阅 webRequest.RequestFilter

此外,请注意您正在传递一个名为 "blocking" 的选项:当您想要修改请求时,必须传递此选项。它使侦听器函数阻止网络请求,因此浏览器会在继续之前等待侦听器返回。有关 "blocking" 的更多信息,请参阅 webRequest.onBeforeRequest 文档。

要进行测试,请打开 MDN 上包含图像的页面(例如,列出扩展用户界面组件的页面),重新加载扩展,然后重新加载 MDN 页面。您会看到类似以下内容

Images on a page replaced with a frog image

修改请求头

最后,使用 webRequest 修改请求头。在此示例中,您更改“User-Agent”头,以便浏览器将自身识别为 Opera 12.16,但仅在访问“https://useragentstring.com/”下的页面时。

更新“manifest.json”以包含 https://useragentstring.com/,如下所示

json
{
  "description": "Demonstrating webRequests",
  "manifest_version": 2,
  "name": "webRequest-demo",
  "version": "1.0",

  "permissions": [
    "webRequest",
    "webRequestBlocking",
    "https://useragentstring.com/"
  ],

  "background": {
    "scripts": ["background.js"]
  }
}

将“background.js”替换为以下代码

js
let targetPage = "https://useragentstring.com/*";

let ua =
  "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16";

function rewriteUserAgentHeader(e) {
  e.requestHeaders.forEach((header) => {
    if (header.name.toLowerCase() === "user-agent") {
      header.value = ua;
    }
  });
  return { requestHeaders: e.requestHeaders };
}

browser.webRequest.onBeforeSendHeaders.addListener(
  rewriteUserAgentHeader,
  { urls: [targetPage] },
  ["blocking", "requestHeaders"],
);

您使用 onBeforeSendHeaders 事件侦听器在发送请求头之前运行函数。

侦听器函数仅针对与 targetPage 模式 匹配的 URL 的请求被调用。此外,请注意您再次传递 "blocking" 作为选项。您还传递 "requestHeaders",这意味着侦听器将传递一个包含您期望发送的请求头的数组。有关这些选项的更多信息,请参阅 webRequest.onBeforeSendHeaders

侦听器函数在请求头数组中查找“User-Agent”头,将其值替换为 ua 变量的值,并返回修改后的数组。此修改后的数组将发送到服务器。

要进行测试,请打开 useragentstring.com 并检查它是否将浏览器识别为 Firefox。然后重新加载扩展程序,重新加载 useragentstring.com,并查看 Firefox 现在是否被识别为 Opera。

useragentstring.com showing details of the modified user agent string

了解更多

要了解有关使用 webRequest API 可以执行的所有操作的信息,请参阅其 参考文档