光域

<html/>

chrome.webRequest 研究

今天说下 chrome.webRequest 的 api 用法, 这个api主要用于处理网络的请求,对应到特定情境中对特定匹配的网络请求进行分析处理,chrome.webRequest api 由九个事件组成,这九个事件是一个网络请求生命周期中的九个不同的阶段,可以说控制的粒度已经很细,基本可以覆盖到特定的时间点。这套api提供了很强大的请求控制功能,因此如果代码有问题,那么后果可能相当严重,在配置manifest.jsonpermission时要注意,最好能够指定到特定的url规则中去,而不是 http://\*\*/\*https://\*\*/\*,这样如果代码出现逻辑错误,那么可能整个浏览器就不能用了,比如你把所有的url都重定向到 一个错误的url去,那么你的浏览器就呵呵了。

下面是这九个事件的关系图:

这九个事件根据请求的顺序最开始是 onBeforeRequest ,最后是 onComplete,基本的顺序如图所示,需要说明的是在onAuthRequired事件之后会再次触发onBeforeSendHeaders,而在onBeforeRedirect之后会重新出发 onBeforeRequest,而如果请求的url是 data或者是file协议,则在执行完onBeforeRequest事件之后会直接触发 onResponseStarted ,在这顺序之下,如果出现错误,都会触发onErrorOccurred事件,也就是说,如果我们对一个网络请求进行监听,那么只有onBeforeRequest事件必定会触发,后面的事件会根据情况才会触发。

下面是每个事件触发的时机和功能:

  • onBeforeRequest : 在一个请求发生的时候,tcp连接之前被触发,可以用于重定向请求或者是进行请求拦截取消
  • onBeforeSendHeaders : 在一个请求发生的时候,初始的http(s) headers已经准备好的时候触发,这个事件主要用于修改发送的头部信息。在这个事件阶段中可以进行请求的拦截取消或者重定向
  • onSendHeaders : 在所有注册了onBeforeSendHeaders事件(可能在不同扩展中)都触发之后,http(s) header发向网络之前触发,这个事件是异步的,触发时不会阻塞http header 发向网络,也就是说不能改变header的信息了。
  • onHeadersReceived : 在http(s) headers 接受的时候触发,这个事件主要用于修改接收到的http(s) headers 。 在这个事件中可以控制请求。
  • onAuthRequired : 在一个请求需要用户认证的时候被触发。
  • onBeforeRedirect : 在一个重定向请求产生的触发,这是一个异步事件,不能控制请求
  • onResponseStarted:在响应的first byte 接收到的时候触发。对于http请求,这个请求触发的时候status line(状态信息) 和 头部都已经获得,这个一个异步事件,不能控制请求。
  • onCompleted : 在一个请求成功之后触发
  • onErrorOccurred : 在一个请求失败时候触发

webRequest API 只会监听在host permission中配置的域名,只对 http、https、ftp、file、chrome-extension 协议起作用,另外有些url是上面协议的,但是被排除在监听范围内,例如 chrome-extension 中其他扩展发出的request,https://www.google.com/chrome 等,都不会被监听到。另外,在扩展中的同步XMLHttpRequest请求也不会被拦截下来,以免造成死锁。另外,有些协议只会触发 本身支持的事件,例如 file:// 协议,只会触发 onBeforeRquest ,onResponseStarted,onCompleted,onErrorOccurred 。

如何去将注册一个事件: 通过事件的 addListener 方法可以注册一个webRequest事件,addListener 接收三个参数,第一个参数是callback方法,会返回一个object对象,其中包含了这次请求的详细信息。具体包括

  • frameId 发出请求的frameId
  • method 请求的方式
  • parentFrameId 发出请求的frameId的父frameId,如果没有,则为-1
  • requestId : 这个Id在一次浏览器的session和一个扩展中是唯一的,用于识别各个请求
  • tabId : 请求发出的tab页面的id,如果是从扩展中发出的,则为-1
  • timeStamp : 请求发出的时间戳
  • type : 请求是由那类元素发出来的
  • url : 请求的url

第二个参数是一个过滤器,用于匹配符合条件的请求,参数如下:

  • urls : urls数组,被匹配到的才会触发回调
  • types : 匹配请求发出的元素类型 ,有 main_frame、sub_frame、stylesheet、script、image、object、xmlhttprequest、other
  • tabId :匹配由哪个tab发出的
  • windowId : 匹配由哪个window发出的

第三个参数是指定是否进行请求阻塞(对于一些特定事件起效),当指定为blocking 之后,回调函数将会是同步的,意味着这个请求将会被阻塞直到回调完成, 这样子我们可以返回一个blickingResponse对请求进行控制,具体如下:

  • cancel : 拦截请求,只能在onBeforeRequest中使用
  • redirectUrl : 重定向请求,只能在onBeforeRequest和onHeadersReceived中使用
  • requestHeaders : 修改request请求http header ,只能在onBeforeSendHeaders中使用
  • responseHeaders : 修改response请求的http header ,只能在onHeadersReceived 中使用
  • authCredentials : 修改验证的username和password信息,只能在onAuthRequired中使用