tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_stale-while-revalidate_max-age-0.js (3248B)


      1 /*
      2 
      3 Tests the Cache-control: stale-while-revalidate response directive.
      4 
      5 Purpose is to check we perform the background revalidation when max-age=0 but
      6 the window is set and we hit it.
      7 
      8 * Make request #1.
      9  - response is from the server and version=1
     10  - max-age=0, stale-while-revalidate=9999
     11 * Switch version of the data on the server and prolong the max-age to not let req #3
     12  do a bck reval at the end of the test (prevent leaks/shutdown races.)
     13 * Make request #2 in 2 seconds (entry should be expired by that time, but fall into
     14  the reval window.)
     15  - response is from the cache, version=1
     16  - a new background request should be made for the data
     17 * Wait for "http-on-background-revalidation" notifying finish of the background reval.
     18 * Make request #3.
     19  - response is from the cache, version=2
     20 * Done.
     21 
     22 */
     23 
     24 "use strict";
     25 
     26 const { HttpServer } = ChromeUtils.importESModule(
     27  "resource://testing-common/httpd.sys.mjs"
     28 );
     29 
     30 let max_age;
     31 let version;
     32 let generate_response = ver => `response version=${ver}`;
     33 
     34 function test_handler(metadata, response) {
     35  const originalBody = generate_response(version);
     36  response.setHeader("Content-Type", "text/html", false);
     37  response.setHeader(
     38    "Cache-control",
     39    `max-age=${max_age}, stale-while-revalidate=9999`,
     40    false
     41  );
     42  response.setStatusLine(metadata.httpVersion, 200, "OK");
     43  response.bodyOutputStream.write(originalBody, originalBody.length);
     44 }
     45 
     46 function make_channel(url) {
     47  return NetUtil.newChannel({
     48    uri: url,
     49    loadUsingSystemPrincipal: true,
     50  }).QueryInterface(Ci.nsIHttpChannel);
     51 }
     52 
     53 async function get_response(channel, fromCache) {
     54  return new Promise(resolve => {
     55    channel.asyncOpen(
     56      new ChannelListener((request, buffer, ctx, isFromCache) => {
     57        Assert.equal(
     58          fromCache,
     59          isFromCache,
     60          `got response from cache = ${fromCache}`
     61        );
     62        resolve(buffer);
     63      })
     64    );
     65  });
     66 }
     67 
     68 async function sleep(time) {
     69  return new Promise(resolve => {
     70    do_timeout(time * 1000, resolve);
     71  });
     72 }
     73 
     74 async function stop_server(httpserver) {
     75  return new Promise(resolve => {
     76    httpserver.stop(resolve);
     77  });
     78 }
     79 
     80 async function background_reval_promise() {
     81  return new Promise(resolve => {
     82    Services.obs.addObserver(resolve, "http-on-background-revalidation");
     83  });
     84 }
     85 
     86 add_task(async function () {
     87  let httpserver = new HttpServer();
     88  httpserver.registerPathHandler("/testdir", test_handler);
     89  httpserver.start(-1);
     90  const PORT = httpserver.identity.primaryPort;
     91  const URI = `http://localhost:${PORT}/testdir`;
     92 
     93  let response;
     94 
     95  version = 1;
     96  max_age = 0;
     97  response = await get_response(make_channel(URI), false);
     98  Assert.equal(response, generate_response(1), "got response ver 1");
     99 
    100  await sleep(2);
    101 
    102  // must specifically wait for the internal channel to finish the reval to make
    103  // the test race-free.
    104  let reval_done = background_reval_promise();
    105 
    106  version = 2;
    107  max_age = 100;
    108  response = await get_response(make_channel(URI), true);
    109  Assert.equal(response, generate_response(1), "got response ver 1");
    110 
    111  await reval_done;
    112 
    113  response = await get_response(make_channel(URI), true);
    114  Assert.equal(response, generate_response(2), "got response ver 2");
    115 
    116  await stop_server(httpserver);
    117 });