tor-browser

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

test_servers.js (11784B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /* import-globals-from head_cache.js */
      8 /* import-globals-from head_cookies.js */
      9 /* import-globals-from head_channels.js */
     10 
     11 // We don't normally allow localhost channels to be proxied, but this
     12 // is easier than updating all the certs and/or domains.
     13 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
     14 registerCleanupFunction(() => {
     15  Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
     16 });
     17 
     18 const { HttpServer } = ChromeUtils.importESModule(
     19  "resource://testing-common/httpd.sys.mjs"
     20 );
     21 const {
     22  NodeHTTPServer,
     23  NodeHTTPSServer,
     24  NodeHTTP2Server,
     25  NodeHTTPProxyServer,
     26  NodeHTTPSProxyServer,
     27  NodeHTTP2ProxyServer,
     28  with_node_servers,
     29 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs");
     30 
     31 function makeChan(uri) {
     32  let chan = NetUtil.newChannel({
     33    uri,
     34    loadUsingSystemPrincipal: true,
     35  }).QueryInterface(Ci.nsIHttpChannel);
     36  chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
     37  return chan;
     38 }
     39 
     40 function channelOpenPromise(chan, flags) {
     41  return new Promise(resolve => {
     42    function finish(req, buffer) {
     43      resolve([req, buffer]);
     44    }
     45    chan.asyncOpen(new ChannelListener(finish, null, flags));
     46  });
     47 }
     48 
     49 function registerSimplePathHandler(server, path) {
     50  return server.registerPathHandler(path, (req, resp) => {
     51    resp.writeHead(200);
     52    resp.end("done");
     53  });
     54 }
     55 
     56 function regiisterServerNamePathHandler(server, path) {
     57  return server.registerPathHandler(path, (req, resp) => {
     58    resp.writeHead(200);
     59    resp.end(global.server_name);
     60  });
     61 }
     62 
     63 add_task(async function test_dual_stack() {
     64  let httpserv = new HttpServer();
     65  let content = "ok";
     66  httpserv.registerPathHandler("/", function handler(metadata, response) {
     67    response.setHeader("Content-Length", `${content.length}`);
     68    response.bodyOutputStream.write(content, content.length);
     69  });
     70  httpserv.start_dualStack(-1);
     71 
     72  let chan = makeChan(`http://127.0.0.1:${httpserv.identity.primaryPort}/`);
     73  let [, response] = await channelOpenPromise(chan);
     74  Assert.equal(response, content);
     75 
     76  chan = makeChan(`http://[::1]:${httpserv.identity.primaryPort}/`);
     77  [, response] = await channelOpenPromise(chan);
     78  Assert.equal(response, content);
     79  await new Promise(resolve => httpserv.stop(resolve));
     80 });
     81 
     82 add_task(async function test_http() {
     83  let server = new NodeHTTPServer();
     84  await server.start();
     85  registerCleanupFunction(async () => {
     86    await server.stop();
     87  });
     88  let chan = makeChan(`http://localhost:${server.port()}/test`);
     89  let req = await new Promise(resolve => {
     90    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
     91  });
     92  equal(req.status, Cr.NS_OK);
     93  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 404);
     94  await registerSimplePathHandler(server, "/test");
     95  chan = makeChan(`http://localhost:${server.port()}/test`);
     96  req = await new Promise(resolve => {
     97    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
     98  });
     99  equal(req.status, Cr.NS_OK);
    100  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    101  equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "http/1.1");
    102  equal(req.QueryInterface(Ci.nsIHttpChannelInternal).isProxyUsed, false);
    103 
    104  await server.stop();
    105 });
    106 
    107 add_task(async function test_https() {
    108  let server = new NodeHTTPSServer();
    109  await server.start();
    110  registerCleanupFunction(async () => {
    111    await server.stop();
    112  });
    113  let chan = makeChan(`https://localhost:${server.port()}/test`);
    114  let req = await new Promise(resolve => {
    115    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    116  });
    117  equal(req.status, Cr.NS_OK);
    118  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 404);
    119  await registerSimplePathHandler(server, "/test");
    120  chan = makeChan(`https://localhost:${server.port()}/test`);
    121  req = await new Promise(resolve => {
    122    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    123  });
    124  equal(req.status, Cr.NS_OK);
    125  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    126  equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "http/1.1");
    127 
    128  await server.stop();
    129 });
    130 
    131 add_task(async function test_http2() {
    132  let server = new NodeHTTP2Server();
    133  await server.start();
    134  registerCleanupFunction(async () => {
    135    await server.stop();
    136  });
    137  let chan = makeChan(`https://localhost:${server.port()}/test`);
    138  let req = await new Promise(resolve => {
    139    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    140  });
    141  equal(req.status, Cr.NS_OK);
    142  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 404);
    143  await registerSimplePathHandler(server, "/test");
    144  chan = makeChan(`https://localhost:${server.port()}/test`);
    145  req = await new Promise(resolve => {
    146    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    147  });
    148  equal(req.status, Cr.NS_OK);
    149  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    150  equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "h2");
    151 
    152  await server.stop();
    153 });
    154 
    155 add_task(async function test_http1_proxy() {
    156  let proxy = new NodeHTTPProxyServer();
    157  await proxy.start();
    158  registerCleanupFunction(async () => {
    159    await proxy.stop();
    160  });
    161 
    162  let chan = makeChan(`http://localhost:${proxy.port()}/test`);
    163  let req = await new Promise(resolve => {
    164    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    165  });
    166  equal(req.status, Cr.NS_OK);
    167  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 405);
    168 
    169  await with_node_servers(
    170    [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
    171    async server => {
    172      await server.execute(
    173        `global.server_name = "${server.constructor.name}";`
    174      );
    175      await regiisterServerNamePathHandler(server, "/test");
    176      let [req1, buff] = await channelOpenPromise(
    177        makeChan(`${server.origin()}/test`),
    178        CL_ALLOW_UNKNOWN_CL
    179      );
    180      equal(req1.status, Cr.NS_OK);
    181      equal(req1.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    182      equal(buff, server.constructor.name);
    183      //Bug 1792187: Check if proxy is set to true when a proxy is used.
    184      equal(req1.QueryInterface(Ci.nsIHttpChannelInternal).isProxyUsed, true);
    185      equal(
    186        req1.QueryInterface(Ci.nsIHttpChannel).protocolVersion,
    187        server.constructor.name == "NodeHTTP2Server" ? "h2" : "http/1.1"
    188      );
    189    }
    190  );
    191 
    192  await proxy.stop();
    193 });
    194 
    195 add_task(async function test_https_proxy() {
    196  let proxy = new NodeHTTPSProxyServer();
    197  await proxy.start();
    198  registerCleanupFunction(async () => {
    199    await proxy.stop();
    200  });
    201 
    202  let chan = makeChan(`https://localhost:${proxy.port()}/test`);
    203  let req = await new Promise(resolve => {
    204    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    205  });
    206  equal(req.status, Cr.NS_OK);
    207  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 405);
    208 
    209  await with_node_servers(
    210    [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
    211    async server => {
    212      await server.execute(
    213        `global.server_name = "${server.constructor.name}";`
    214      );
    215      await regiisterServerNamePathHandler(server, "/test");
    216 
    217      let [req1, buff] = await channelOpenPromise(
    218        makeChan(`${server.origin()}/test`),
    219        CL_ALLOW_UNKNOWN_CL
    220      );
    221      equal(req1.status, Cr.NS_OK);
    222      equal(req1.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    223      equal(buff, server.constructor.name);
    224    }
    225  );
    226 
    227  await proxy.stop();
    228 });
    229 
    230 add_task(async function test_http2_proxy() {
    231  let proxy = new NodeHTTP2ProxyServer();
    232  await proxy.start();
    233  registerCleanupFunction(async () => {
    234    await proxy.stop();
    235  });
    236 
    237  let chan = makeChan(`https://localhost:${proxy.port()}/test`);
    238  let req = await new Promise(resolve => {
    239    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    240  });
    241  equal(req.status, Cr.NS_OK);
    242  equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 405);
    243 
    244  await with_node_servers(
    245    [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
    246    async server => {
    247      await server.execute(
    248        `global.server_name = "${server.constructor.name}";`
    249      );
    250      await regiisterServerNamePathHandler(server, "/test");
    251      let [req1, buff] = await channelOpenPromise(
    252        makeChan(`${server.origin()}/test`),
    253        CL_ALLOW_UNKNOWN_CL
    254      );
    255      equal(req1.status, Cr.NS_OK);
    256      equal(req1.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    257      equal(buff, server.constructor.name);
    258    }
    259  );
    260 
    261  await proxy.stop();
    262 });
    263 
    264 add_task(async function test_proxy_with_redirects() {
    265  let proxies = [
    266    NodeHTTPProxyServer,
    267    NodeHTTPSProxyServer,
    268    NodeHTTP2ProxyServer,
    269  ];
    270  for (let p of proxies) {
    271    let proxy = new p();
    272    await proxy.start();
    273    registerCleanupFunction(async () => {
    274      await proxy.stop();
    275    });
    276 
    277    await with_node_servers(
    278      [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
    279      async server => {
    280        info(`Testing ${p.name} with ${server.constructor.name}`);
    281        await server.execute(
    282          `global.server_name = "${server.constructor.name}";`
    283        );
    284        await server.registerPathHandler("/redirect", (req, resp) => {
    285          resp.writeHead(302, {
    286            Location: "/test",
    287          });
    288          resp.end(global.server_name);
    289        });
    290        await server.registerPathHandler("/test", (req, resp) => {
    291          resp.writeHead(200);
    292          resp.end(global.server_name);
    293        });
    294 
    295        let chan = makeChan(`${server.origin()}/redirect`);
    296        let [req, buff] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
    297        equal(req.status, Cr.NS_OK);
    298        equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    299        equal(buff, server.constructor.name);
    300        req.QueryInterface(Ci.nsIProxiedChannel);
    301        ok(!!req.proxyInfo);
    302        notEqual(req.proxyInfo.type, "direct");
    303      }
    304    );
    305    await proxy.stop();
    306  }
    307 });
    308 
    309 add_task(async function test_async_event() {
    310  let server = new NodeHTTP2Server();
    311  await server.start();
    312  registerCleanupFunction(async () => {
    313    await server.stop();
    314  });
    315 
    316  await server.execute(`new Promise(r => setTimeout(r, 500))`);
    317 
    318  await server.stop();
    319 });
    320 
    321 add_task(async function test_async_state_management() {
    322  let server = new NodeHTTP2Server();
    323  await server.start();
    324  registerCleanupFunction(async () => {
    325    await server.stop();
    326  });
    327 
    328  await server.execute(`global.asyncResults = [];`);
    329 
    330  await server.execute(`
    331    global.asyncCounter = 0;
    332    global.performAsyncOperation = function(delay, value) {
    333      return new Promise(resolve => {
    334        setTimeout(() => {
    335          global.asyncCounter++;
    336          global.asyncResults.push({ counter: global.asyncCounter, value });
    337          resolve({ counter: global.asyncCounter, value });
    338        }, delay);
    339      });
    340    };
    341  `);
    342 
    343  let op1 = server.execute(`performAsyncOperation(100, "first")`);
    344  let op2 = server.execute(`performAsyncOperation(50, "second")`);
    345 
    346  let result1 = await op1;
    347  let result2 = await op2;
    348  // This ran after 100 ms, so it comes in second
    349  equal(result1.counter, 2);
    350  equal(result1.value, "first");
    351 
    352  // this rand after 50 ms, so it comes in first.
    353  equal(result2.counter, 1);
    354  equal(result2.value, "second");
    355 
    356  let results = await server.execute(`global.asyncResults`);
    357  equal(results.length, 2);
    358  equal(results[0].value, "second");
    359  equal(results[1].value, "first");
    360 
    361  let counter = await server.execute(`global.asyncCounter`);
    362  equal(counter, 2);
    363 
    364  await server.stop();
    365 });