该页面翻译自 Google Chrome Extensions 与 Google Chrome Apps。除非特别说明,该页面的内容遵循 Creative Commons Attribution 3.0 License,代码示例遵循 BSD License。
描述: |
使用 chrome.webRequest API 监控与分析流量,还可以实时地拦截、阻止或者修改请求。
|
可用版本: |
从 Chrome 17 开始稳定支持。
|
权限: |
"webRequest"
主机权限 |
要使用网络请求 API,您必须在扩展程序的清单文件中声明 "webRequest" 权限,以及您需要访问网络请求的所有主机的主机权限。如果您需要以阻塞方式使用网络请求 API,您还需要另外请求 "webRequestBlocking" 权限。例如:
{ "name": "我的扩展程序", ... "permissions": [ "webRequest", "*://*.google.com/" ], ... }
网络请求 API 定义了一系列事件,在一次网络请求的生命周期内产生,您可以使用这些事件监控和分析流量。某些同步事件还允许您截获、阻止或者修改请求。
对于成功请求的事件生命周期如下图所示,接下来是事件的定义:
onBeforeRequest
(可以为同步)onBeforeSendHeaders
(可以为同步)onBeforeSendHeaders
事件将传递给所有订阅者,所以不同的订阅者都可以尝试修改请求。有关具体如何处理的细节,请参见实现细节部分。这一事件可以用来取消请求。
onSendHeaders
onHeadersReceived
(可以为同步)onAuthRequired
(可以为同步)onBeforeRedirect
onResponseStarted
onCompleted
onErrorOccurred
onCompleted
或
onErrorOccurred
是最终产生的事件,除了如下例外:如果请求重定向至
data://
URL,onBeforeRedirect
将是最后报告的事件。
(*)注意网络请求 API 向扩展程序展现的是网络栈的一种抽象。单个 URL 请求在内部可以分割为几个 HTTP 请求(例如从一个大文件获取单独的字节范围)或者可以不与网络通信就由网络栈处理。由于这一原因,这一 API 不会提供最终发送至网络的的 HTTP 头信息。例如,所有与缓存相关的头信息对扩展程序都是不可见的。
如下是当前不提供给 onBeforeSendHeaders 事件的头信息列表,这一列表不保证是完整的或者不会变化:
只有扩展程序具有相应的主机权限时,网络请求 API
才会暴露相关的请求。此外,只能访问下列协议的请求:http://
、https://
、ftp://
、file://
或
chrome-extension://
。
此外,某些请求的 URL 即使使用了以上某种协议也会被隐藏。例如,chrome-extension://other_extension_id
,其中
other_extension_id
不是处理该请求的扩展程序标识符;还有
https://www.google.com/chrome
及其他(该列表并不完整)。此外来自您的扩展程序的同步 XMLHttpRequest
将对阻塞的事件处理函数隐藏,以免产生死锁。注意,对于一些支持的协议,由于对应协议本身的性质,可以产生的事件会受到限制。例如,对于
file:
协议,只会产生 onBeforeRequest
、onResponseStarted
、onCompleted
和
onErrorOccurred
事件。
如以下几节所述,网络请求 API 的事件使用请求标识符,当您注册事件监听器时您还可以指定过滤器以及可选的额外信息。
每一个请求由请求标识符标识,这一标识符在浏览器会话以及扩展程序的上下文中保证唯一,在请求的生命周期内保持不变,可以用来匹配同一请求的其他事件。注意在 HTTP 重定向或 HTTP 认证时,多个 HTTP 请求将映射至同一个网络请求。
要为网络请求注册事件处理函数,您使用通常
addListener()
函数的一种变形。除了指定回调函数,您还必须指定过滤器参数,另外您还可以指定一个可选的额外信息参数。
网络请求API的 addListener()
三个参数定义如下:
var callback = function(details) {...}; var filter = {...}; var opt_extraInfoSpec = [...];
如下是监听 onBeforeRequest
事件的一个例子:
chrome.webRequest.onBeforeRequest.addListener( callback, filter, opt_extraInfoSpec);
每一个 addListener()
调用必须传递回调函数,作为第一个参数。将向这一回调函数传递包含当前
URL 请求详情的词典,词典中的信息取决于具体事件类型以及
opt_extraInfoSpec
的内容。
如果可选的 opt_extraInfoSpec
数组包含 'blocking'
字符串(仅允许用于特定事件),回调函数将以同步方式处理。这意味着请求将阻塞,直到回调函数返回。在这一种情况下,回调函数可以返回
BlockingResponse
对象,确定这一请求进一步的生命周期。取决于当前上下文,这一响应允许取消或重定向某个请求(OnBeforeRequest
),取消请求或修改头信息(onBeforeSendHeaders
),或者提供认证凭据(onAuthRequired
)。
RequestFilter 类型的 filter
参数允许通过不同的方式限制为哪些请求产生事件:
*://www.google.com/foo*bar
。"main_frame"
(为顶层框架加载的文档)、"sub_frame"
(为内嵌框架加载的文档)和
"image"
(网站上的图片)。请参见
RequestFilter。
取决于事件类型,您可以在 opt_extraInfoSpec
中指定字符串,获取有关请求的附加信息。这样是为了仅在明确请求时才提供请求数据的有关详情。
在开发使用网络请求API的扩展程序时,理解如下几个实现细节是很重要的:
在网络请求 API
的当前实现中,如果至少一个扩展程序要求取消请求,则请求将被取消。如果一个扩展程序取消了一个请求,所有扩展程序都会收到
onErrorOccurred
事件的通知。一次只有一个扩展程序允许重定向请求或者修改头信息。如果多于一个扩展程序尝试修改请求,最近安装的扩展程序具有优先级,而忽略所有其他扩展程序。如果扩展程序修改或重定向的要求被忽略,也不会收到通知。
Chrome
浏览器使用两种缓存:磁盘缓存和十分快速的内存缓存。内存缓存的生命周期与渲染器进程(大致与每个标签页对应)的生命周期相关,通过内存缓存响应的请求对网络请求API不可见。如果请求处理函数更改了它的行为(例如根据哪些请求被阻止而作出的行为),简单的页面刷新不一定能够体现这一更改的行为。要确保行为更改生效,请调用
handlerBehaviorChanged()
来清洗内存缓存。然而不要经常调用,清洗缓存是一项十分昂贵的操作。您不需要在注册或取消注册事件处理函数后调用
handlerBehaviorChanged()
。
网络请求事件的 timeStamp
属性仅保证内部的一致性,将两个事件的时间相比较会得到它们之间正确的时间差,但是与扩展程序内的当前时间(例如通过
(new Date()).getTime()
)比较则可能会导致不可预料的结果。
如下例子演示如何阻止所有发送至 www.evil.com
的请求:
chrome.webRequest.onBeforeRequest.addListener( function(details) { return {cancel: details.url.indexOf("://www.evil.com/") != -1}; }, {urls: ["<all_urls>"]}, ["blocking"]);
由于这一函数使用了阻塞事件处理函数,您将需要在清单文件中声明 "webRequest" 以及 "webRequestBlocking" 权限。
以下例子通过另一种更高效的方式达到相同目的,因为不发送至 www.evil.com
的请求不必传递给扩展程序:
chrome.webRequest.onBeforeRequest.addListener( function(details) { return {cancel: true}; }, {urls: ["*://www.evil.com/*"]}, ["blocking"]);
以下例子演示如何将所有请求中的 User-Agent 头信息删除:
chrome.webRequest.onBeforeSendHeaders.addListener( function(details) { for (var i = 0; i < details.requestHeaders.length; ++i) { if (details.requestHeaders[i].name === 'User-Agent') { details.requestHeaders.splice(i, 1); break; } } return {requestHeaders: details.requestHeaders}; }, {urls: ["<all_urls>"]}, ["blocking", "requestHeaders"]);
有关更多示例代码,请参见网络请求示例。
name
属性,以及 value
或 binaryValue
中的某一属性。responseHeaders
),只有有当您确实需要修改头信息时才应该返回 responseHeaders
。
20
)handlerBehaviorChanged
能够被调用的次数。handlerBehaviorChanged
是一个昂贵的函数,不应该经常调用。
当请求即将发生时产生。
"blocking"
, or "requestBody"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
在发送 HTTP 请求前,一旦请求头信息可用就产生这一事件。这一事件可能在与服务器的 TCP 连接建立后产生,但是确保在发送任何 HTTP 数据前产生。
"requestHeaders"
, or "blocking"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当请求即将发送至服务器的前一刻产生(前面 onBeforeSendHeaders 事件处理函数作出的修改可以在这一事件产生时体现)。
"requestHeaders"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当接收到 HTTP 响应头信息时产生。
"blocking"
, or "responseHeaders"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当接收到认证失败时产生。事件处理函数有三种选择:提供认证凭据,取消请求并显示错误页面,或者不采取任何行动。如果提供了错误的用户凭据,可能会为同一请求重复调用事件处理函数。
"responseHeaders"
, "blocking"
, or "asyncBlocking"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details, function callback) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当响应正文的第一个字节接收到时产生。对于 HTTP 请求,这意味着状态行及请求头信息已经可用。
"responseHeaders"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当服务器产生的重定向即将进行时产生。
"responseHeaders"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当请求完成时产生。
"responseHeaders"
extraInfoSpec)
callback 参数应该指定一个如下形式的函数:
function(object details) {...};
type
为 "main_frame"
或 "sub_frame"
),frameId
指定该框架的标识符,而不是外层框架的标识符。框架标识符在标签页中保证唯一。
"main_frame"
, "sub_frame"
, "stylesheet"
, "script"
, "image"
, "object"
, "xmlhttprequest"
, or "other"
)
当错误发生时产生。
callback 参数应该指定一个如下形式的函数:
function(object details) {...};