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