Home | History | Annotate | Download | only in intros
      1 <h2 id="manifest">Manifest</h2>
      2 <p>You must declare the "webRequest" permission in the <a
      3   href="manifest">extension manifest</a> to use the web request
      4 API, along with <a href="declare_permissions">host permissions</a>
      5 for any hosts whose network requests you want to access. If you want to
      6 use the web request API in a blocking fashion, you need to request
      7 the "webRequestBlocking" permission in addition.
      8 For example:</p>
      9 <pre data-filename="manifest.json">
     10 {
     11   "name": "My extension",
     12   ...
     13   <b>"permissions": [
     14     "webRequest",
     15     "*://*.google.com/"
     16   ]</b>,
     17   ...
     18 }
     19 </pre>
     20 
     21 <h2 id="life_cycle">Life cycle of requests</h2>
     22 
     23 <p>
     24 The web request API defines a set of events that follow the life cycle of a web
     25 request. You can use these events to observe and analyze traffic. Certain
     26 synchronous events will allow you to intercept, block, or modify a request.
     27 </p>
     28 
     29 <p>
     30 The event life cycle for successful requests is illustrated here, followed by
     31 event definitions:<br/>
     32 <img src="{{static}}/images/webrequestapi.png"
     33   width="385" height="503"
     34   alt="Life cycle of a web request from the perspective of the webrequest API"
     35   style="margin-left: auto; margin-right: auto; display: block"/>
     36 </p>
     37 
     38 <p>
     39 <dl>
     40   <dt><code>onBeforeRequest</code> (optionally synchronous)</dt>
     41   <dd>Fires when a request is about to occur. This event is sent before any TCP
     42   connection is made and can be used to cancel or redirect requests.</dd>
     43   <dt><code>onBeforeSendHeaders</code> (optionally synchronous)</dt>
     44   <dd>Fires when a request is about to occur and the initial headers have been
     45   prepared. The event is intended to allow extensions to add, modify, and delete
     46   request headers <a href="#life_cycle_footnote">(*)</a>. The
     47   <code>onBeforeSendHeaders</code> event is passed to all subscribers, so
     48   different subscribers may attempt to modify the request; see the <a
     49     href="#implementation">Implementation details</a> section for how this is
     50   handled. This event can be used to cancel the request.</dd>
     51   <dt><code>onSendHeaders</code></dt>
     52   <dd>Fires after all extensions have had a chance to modify the request
     53   headers, and presents the final <a href="#life_cycle_footnote">(*)</a>
     54   version. The event is triggered before the headers are sent to the network.
     55   This event is informational and handled asynchronously. It does not allow
     56   modifying or cancelling the request.</dd>
     57   <dt><code>onHeadersReceived</code> (optionally synchronous)</dt>
     58   <dd>Fires each time that an HTTP(S) response header is received. Due
     59   to redirects and authentication requests this can happen multiple times per
     60   request. This event is intended to allow extensions to add, modify, and delete
     61   response headers, such as incoming Set-Cookie headers. The caching directives
     62   are processed before this event is triggered, so modifying headers such as
     63   Cache-Control has no influence on the browser's cache.
     64   It also allows you to redirect the request.</dd>
     65   <dt><code>onAuthRequired</code> (optionally synchronous)</dt>
     66   <dd>Fires when a request requires authentication of the user. This event can
     67   be handled synchronously to provide authentication credentials. Note that
     68   extensions may provide invalid credentials. Take care not to enter an infinite
     69   loop by repeatedly providing invalid credentials.</dd>
     70   <dt><code>onBeforeRedirect</code></dt>
     71   <dd>Fires when a redirect is about to be executed. A redirection can be
     72   triggered by an HTTP response code or by an extension. This event is
     73   informational and handled asynchronously. It does not allow you to modify or
     74   cancel the request. </dd>
     75   <dt><code>onResponseStarted</code></dt>
     76   <dd>Fires when the first byte of the response body is received. For HTTP
     77   requests, this means that the status line and response headers are
     78   available. This event is informational and handled asynchronously. It does not
     79   allow modifying or cancelling the request.</dd>
     80   <dt><code>onCompleted</code></dt>
     81   <dd>Fires when a request has been processed successfully.</dd>
     82   <dt><code>onErrorOccurred</code></dt>
     83   <dd>Fires when a request could not be processed successfully.</dd>
     84 </dl>
     85 The web request API guarantees that for each request either
     86 <code>onCompleted</code> or <code>onErrorOccurred</code> is fired as the final
     87 event with one exception: If a request is redirected to a <code>data://</code>
     88 URL, <code>onBeforeRedirect</code> is the last reported event.
     89 </p>
     90 
     91 <p id="life_cycle_footnote">(*) Note that the web request API presents an
     92 abstraction of the network stack to the extension. Internally, one URL request
     93 can be split into several HTTP requests (for example to fetch individual byte
     94 ranges from a large file) or can be handled by the network stack without
     95 communicating with the network. For this reason, the API does not provide the
     96 final HTTP headers that are sent to the network. For example, all headers that
     97 are related to caching are invisible to the extension.</p>
     98 
     99 <p>The following headers are currently <b>not provided</b> to the
    100 <code>onBeforeSendHeaders</code> event. This list is not guaranteed to be
    101 complete nor stable.
    102 <ul>
    103   <li>Authorization</li>
    104   <li>Cache-Control</li>
    105   <li>Connection</li>
    106   <li>Content-Length</li>
    107   <li>Host</li>
    108   <li>If-Modified-Since</li>
    109   <li>If-None-Match</li>
    110   <li>If-Range</li>
    111   <li>Partial-Data</li>
    112   <li>Pragma</li>
    113   <li>Proxy-Authorization</li>
    114   <li>Proxy-Connection</li>
    115   <li>Transfer-Encoding</li>
    116 </ul>
    117 </p>
    118 
    119 <p>
    120 The webRequest API only exposes requests that the extension has
    121 permission to see, given its
    122 <a href="declare_permissions">host permissions</a>.
    123 Moreover, only the following schemes are accessible:
    124 <code>http://</code>,
    125 <code>https://</code>,
    126 <code>ftp://</code>,
    127 <code>file://</code>, or
    128 <code>chrome-extension://</code>.
    129 In addition, even certain requests with URLs using one of the above schemes
    130 are hidden, e.g.,
    131 <code>chrome-extension://other_extension_id</code> where
    132 <code>other_extension_id</code> is not the ID of the extension to handle
    133 the request,
    134 <code>https://www.google.com/chrome</code>,
    135 and others (this list is not complete). Also synchronous XMLHttpRequests from
    136 your extension are hidden from blocking event handlers in order to prevent
    137 deadlocks.
    138 Note that for some of the supported schemes the set of available events might be
    139 limited due to the nature of the corresponding protocol.
    140 For example, for the <q>file:</q> scheme, only <code>onBeforeRequest</code>,
    141 <code>onResponseStarted</code>, <code>onCompleted</code>, and
    142 <code>onErrorOccurred</code> may be dispatched.
    143 </p>
    144 
    145 <h2 id="concepts">Concepts</h2>
    146 
    147 <p>As the following sections explain, events in the web request API use request
    148 IDs, and you can optionally specify filters and extra information when you
    149 register event listeners.</p>
    150 
    151 <h3 id="Request IDs">Request IDs</h3>
    152 
    153 <p>Each request is identified by a request ID. This ID is unique within a
    154 browser session and the context of an extension. It remains constant during the
    155 the life cycle of a request and can be used to match events for the same
    156 request. Note that several HTTP requests are mapped to one web request in case
    157 of HTTP redirection or HTTP authentication.</p>
    158 
    159 <h3 id="subscription">Registering event listeners</h3>
    160 
    161 <p>To register an event listener for a web request, you use a variation on the
    162 <a href="events">usual <code>addListener()</code> function</a>.
    163 In addition to specifying a callback function,
    164 you have to specify a filter argument and you may specify an optional extra info
    165 argument.</p>
    166 
    167 <p>The three arguments to the web request API's <code>addListener()</code> have
    168 the following definitions:</p>
    169 <pre>
    170 var callback = function(details) {...};
    171 var filter = {...};
    172 var opt_extraInfoSpec = [...];
    173 </pre>
    174 
    175 <p>Here's an example of listening for the <code>onBeforeRequest</code>
    176 event:</p>
    177 <pre>
    178 chrome.webRequest.onBeforeRequest.addListener(
    179   callback, filter, opt_extraInfoSpec);
    180 </pre>
    181 
    182 <p>Each <code>addListener()</code> call takes a mandatory callback function as
    183 the first parameter. This callback function is passed a dictionary containing
    184 information about the current URL request. The information in this dictionary
    185 depends on the specific event type as well as the content of
    186 <code>opt_extraInfoSpec</code>.</p>
    187 
    188 <p>If the optional <code>opt_extraInfoSpec</code> array contains the string
    189 <code>'blocking'</code> (only allowed for specific events), the callback
    190 function is handled synchronously. That means that the request is blocked until
    191 the callback function returns. In this case, the callback can return a
    192   $(ref:webRequest.BlockingResponse) that determines the further
    193 life cycle of the request. Depending on the context, this response allows
    194 cancelling or redirecting a request (<code>onBeforeRequest</code>), cancelling a
    195 request or modifying headers (<code>onBeforeSendHeaders</code>,
    196 <code>onHeadersReceived</code>), or providing authentication credentials
    197 (<code>onAuthRequired</code>).</p>
    198 
    199 <p>The $(ref:webRequest.RequestFilter)
    200 <code>filter</code> allows limiting the requests for which events are
    201 triggered in various dimensions:
    202 <dl>
    203   <dt>URLs</dt>
    204   <dd><a href="match_patterns">URL patterns</a> such as
    205   <code>*://www.google.com/foo*bar</code>.</dd>
    206   <dt>Types</dt>
    207   <dd>Request types such as <code>main_frame</code> (a document that is loaded
    208   for a top-level frame), <code>sub_frame</code> (a document that is loaded for
    209   an embedded frame), and <code>image</code> (an image on a web site).
    210   See $(ref:webRequest.RequestFilter).</dd>
    211   <dt>Tab ID</dt>
    212   <dd>The identifier for one tab.</dd>
    213   <dt>Window ID</dt>
    214   <dd>The identifier for a window.</dd>
    215 </p>
    216 
    217 <p>Depending on the event type, you can specify strings in
    218 <code>opt_extraInfoSpec</code> to ask for additional information about the
    219 request. This is used to provide detailed information on request's data only
    220 if explicitly requested.</p>
    221 
    222 <h2 id="implementation">Implementation details</h2>
    223 
    224 <p>Several implementation details can be important to understand when developing
    225 an extension that uses the web request API:</p>
    226 
    227 <h3 id="conflict_resolution">Conflict resolution</h3>
    228 <p>In the current implementation of the web request API, a request is considered
    229 as cancelled if at least one extension instructs to cancel the request. If
    230 an extension cancels a request, all extensions are notified by an
    231 <code>onErrorOccurred</code> event. Only one extension is allowed to redirect a
    232 request or modify a header at a time. If more than one extension attempts to
    233 modify the request, the most recently installed extension wins and all others
    234 are ignored. An extension is not notified if its instruction to modify or
    235 redirect has been ignored.</p>
    236 
    237 <h3 id="caching">Caching</h3>
    238 <p>
    239 Chrome employs two caches &mdash; an on-disk cache and a very fast in-memory
    240 cache.  The lifetime of an in-memory cache is attached to the lifetime of a
    241 render process, which roughly corresponds to a tab. Requests that are answered
    242 from the in-memory cache are invisible to the web request API. If a request
    243 handler changes its behavior (for example, the behavior according to which
    244 requests are blocked), a simple page refresh might not respect this changed
    245 behavior.  To make sure the behavior change goes through, call
    246 <code>handlerBehaviorChanged()</code> to flush the in-memory cache. But don't do
    247 it often; flushing the cache is a very expensive operation. You don't need to
    248 call <code>handlerBehaviorChanged()</code> after registering or unregistering an
    249 event listener.</p>
    250 
    251 <h3 id="timestamps">Timestamps</h3>
    252 <p>
    253 The <code>timestamp</code> property of web request events is only guaranteed to
    254 be <i>internally</i> consistent. Comparing one event to another event will give
    255 you the correct offset between them, but comparing them to the current time
    256 inside the extension (via <code>(new Date()).getTime()</code>, for instance)
    257 might give unexpected results.
    258 </p>
    259 
    260 <h3 id="error_handling">Error handling</h3>
    261 <p>
    262 If you try to register an event with invalid arguments, then a JavaScript error
    263 will be thrown, and the event handler will not be registered.
    264 
    265 If an error is thrown while an event is handled, or if an event handler returns
    266 an invalid blocking response, an error message is logged to your extension's
    267 console and the handler is ignored for that request.
    268 </p>
    269 
    270 <h2 id="examples">Examples</h2>
    271 
    272 <p>The following example illustrates how to block all requests to
    273 <code>www.evil.com</code>:</p>
    274 <pre>
    275 chrome.webRequest.onBeforeRequest.addListener(
    276   function(details) {
    277     return {cancel: details.url.indexOf("://www.evil.com/") != -1};
    278   },
    279   {urls: ["&lt;all_urls&gt;"]},
    280   ["blocking"]);
    281 </pre>
    282 
    283 <p>As this function uses a blocking event handler, it requires the "webRequest"
    284 as well as the "webRequestBlocking" permission in the manifest file.</p>
    285 
    286 <p>The following example achieves the same goal in a more efficient way because
    287 requests that are not targeted to <code>www.evil.com</code> do not need to be
    288 passed to the extension:</p>
    289 <pre>
    290 chrome.webRequest.onBeforeRequest.addListener(
    291   function(details) { return {cancel: true}; },
    292   {urls: ["*://www.evil.com/*"]},
    293   ["blocking"]);
    294 </pre>
    295 
    296 <p>The following example illustrates how to delete the User-Agent header from
    297 all requests:</p>
    298 <pre>
    299 chrome.webRequest.onBeforeSendHeaders.addListener(
    300   function(details) {
    301     for (var i = 0; i < details.requestHeaders.length; ++i) {
    302       if (details.requestHeaders[i].name === 'User-Agent') {
    303         details.requestHeaders.splice(i, 1);
    304         break;
    305       }
    306     }
    307     return {requestHeaders: details.requestHeaders};
    308   },
    309   {urls: ["&lt;all_urls&gt;"]},
    310   ["blocking", "requestHeaders"]);
    311 </pre>
    312 
    313 <p> For more example code, see the <a href="samples#webrequest">web request
    314 samples</a>.</p>
    315