tor-browser

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

test_restrequest.js (26106B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { RESTRequest } = ChromeUtils.importESModule(
      7  "resource://services-common/rest.sys.mjs"
      8 );
      9 
     10 function run_test() {
     11  Log.repository.getLogger("Services.Common.RESTRequest").level =
     12    Log.Level.Trace;
     13  initTestLogging("Trace");
     14 
     15  run_next_test();
     16 }
     17 
     18 /**
     19 * Initializing a RESTRequest with an invalid URI throws
     20 * NS_ERROR_MALFORMED_URI.
     21 */
     22 add_test(function test_invalid_uri() {
     23  do_check_throws(function () {
     24    new RESTRequest("an invalid URI");
     25  }, Cr.NS_ERROR_MALFORMED_URI);
     26  run_next_test();
     27 });
     28 
     29 /**
     30 * Verify initial values for attributes.
     31 */
     32 add_test(function test_attributes() {
     33  let uri = "http://foo.com/bar/baz";
     34  let request = new RESTRequest(uri);
     35 
     36  Assert.ok(request.uri instanceof Ci.nsIURI);
     37  Assert.equal(request.uri.spec, uri);
     38  Assert.equal(request.response, null);
     39  Assert.equal(request.status, request.NOT_SENT);
     40  let expectedLoadFlags =
     41    Ci.nsIRequest.LOAD_BYPASS_CACHE |
     42    Ci.nsIRequest.INHIBIT_CACHING |
     43    Ci.nsIRequest.LOAD_ANONYMOUS;
     44  Assert.equal(request.loadFlags, expectedLoadFlags);
     45 
     46  run_next_test();
     47 });
     48 
     49 /**
     50 * Verify that a proxy auth redirect doesn't break us. This has to be the first
     51 * request made in the file!
     52 */
     53 add_task(async function test_proxy_auth_redirect() {
     54  let pacFetched = false;
     55  function pacHandler(metadata, response) {
     56    pacFetched = true;
     57    let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }';
     58    response.setStatusLine(metadata.httpVersion, 200, "OK");
     59    response.setHeader(
     60      "Content-Type",
     61      "application/x-ns-proxy-autoconfig",
     62      false
     63    );
     64    response.bodyOutputStream.write(body, body.length);
     65  }
     66 
     67  let fetched = false;
     68  function original(metadata, response) {
     69    fetched = true;
     70    let body = "TADA!";
     71    response.setStatusLine(metadata.httpVersion, 200, "OK");
     72    response.bodyOutputStream.write(body, body.length);
     73  }
     74 
     75  let server = httpd_setup({
     76    "/original": original,
     77    "/pac3": pacHandler,
     78  });
     79  PACSystemSettings.PACURI = server.baseURI + "/pac3";
     80  installFakePAC();
     81 
     82  let req = new RESTRequest(server.baseURI + "/original");
     83  await req.get();
     84 
     85  Assert.ok(pacFetched);
     86  Assert.ok(fetched);
     87 
     88  Assert.ok(req.response.success);
     89  Assert.equal("TADA!", req.response.body);
     90  uninstallFakePAC();
     91  await promiseStopServer(server);
     92 });
     93 
     94 /**
     95 * Ensure that failures that cause asyncOpen to throw
     96 * result in callbacks being invoked.
     97 * Bug 826086.
     98 */
     99 add_task(async function test_forbidden_port() {
    100  let request = new RESTRequest("http://localhost:6000/");
    101 
    102  await Assert.rejects(
    103    request.get(),
    104    error => error.result == Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED
    105  );
    106 });
    107 
    108 /**
    109 * Demonstrate API short-hand: create a request and dispatch it immediately.
    110 */
    111 add_task(async function test_simple_get() {
    112  let handler = httpd_handler(200, "OK", "Huzzah!");
    113  let server = httpd_setup({ "/resource": handler });
    114  let request = new RESTRequest(server.baseURI + "/resource");
    115  let promiseResponse = request.get();
    116 
    117  Assert.equal(request.status, request.SENT);
    118  Assert.equal(request.method, "GET");
    119 
    120  let response = await promiseResponse;
    121  Assert.equal(response, request.response);
    122 
    123  Assert.equal(request.status, request.COMPLETED);
    124  Assert.ok(response.success);
    125  Assert.equal(response.status, 200);
    126  Assert.equal(response.body, "Huzzah!");
    127  await promiseStopServer(server);
    128 });
    129 
    130 /**
    131 * Test HTTP GET with all bells and whistles.
    132 */
    133 add_task(async function test_get() {
    134  let handler = httpd_handler(200, "OK", "Huzzah!");
    135  let server = httpd_setup({ "/resource": handler });
    136 
    137  let request = new RESTRequest(server.baseURI + "/resource");
    138  Assert.equal(request.status, request.NOT_SENT);
    139 
    140  let promiseResponse = request.get();
    141 
    142  Assert.equal(request.status, request.SENT);
    143  Assert.equal(request.method, "GET");
    144 
    145  Assert.ok(!!(request.channel.loadFlags & Ci.nsIRequest.LOAD_BYPASS_CACHE));
    146  Assert.ok(!!(request.channel.loadFlags & Ci.nsIRequest.INHIBIT_CACHING));
    147 
    148  let response = await promiseResponse;
    149 
    150  Assert.equal(response, request.response);
    151  Assert.equal(request.status, request.COMPLETED);
    152  Assert.ok(request.response.success);
    153  Assert.equal(request.response.status, 200);
    154  Assert.equal(request.response.body, "Huzzah!");
    155  Assert.equal(handler.request.method, "GET");
    156 
    157  await Assert.rejects(request.get(), /Request has already been sent/);
    158 
    159  await promiseStopServer(server);
    160 });
    161 
    162 /**
    163 * Test HTTP GET with UTF-8 content, and custom Content-Type.
    164 */
    165 add_task(async function test_get_utf8() {
    166  let response = "Hello World or Καλημέρα κόσμε or こんにちは 世界 😺";
    167 
    168  let contentType = "text/plain";
    169  let charset = true;
    170  let charsetSuffix = "; charset=UTF-8";
    171 
    172  let server = httpd_setup({
    173    "/resource": function (req, res) {
    174      res.setStatusLine(req.httpVersion, 200, "OK");
    175      res.setHeader(
    176        "Content-Type",
    177        contentType + (charset ? charsetSuffix : "")
    178      );
    179 
    180      let converter = Cc[
    181        "@mozilla.org/intl/converter-output-stream;1"
    182      ].createInstance(Ci.nsIConverterOutputStream);
    183      converter.init(res.bodyOutputStream, "UTF-8");
    184      converter.writeString(response);
    185      converter.close();
    186    },
    187  });
    188 
    189  // Check if charset in Content-Type is propertly interpreted.
    190  let request1 = new RESTRequest(server.baseURI + "/resource");
    191  await request1.get();
    192 
    193  Assert.equal(request1.response.status, 200);
    194  Assert.equal(request1.response.body, response);
    195  Assert.equal(
    196    request1.response.headers["content-type"],
    197    contentType + charsetSuffix
    198  );
    199 
    200  // Check that we default to UTF-8 if Content-Type doesn't have a charset
    201  charset = false;
    202  let request2 = new RESTRequest(server.baseURI + "/resource");
    203  await request2.get();
    204  Assert.equal(request2.response.status, 200);
    205  Assert.equal(request2.response.body, response);
    206  Assert.equal(request2.response.headers["content-type"], contentType);
    207  Assert.equal(request2.response.charset, "utf-8");
    208 
    209  let request3 = new RESTRequest(server.baseURI + "/resource");
    210 
    211  // With the test server we tend to get onDataAvailable in chunks of 8192 (in
    212  // real network requests there doesn't appear to be any pattern to the size of
    213  // the data `onDataAvailable` is called with), the smiling cat emoji encodes as
    214  // 4 bytes, and so when utf8 encoded, the `"a" + "😺".repeat(2048)` will not be
    215  // aligned onto a codepoint.
    216  //
    217  // Since 8192 isn't guaranteed and could easily change, the following string is
    218  // a) very long, and b) misaligned on roughly 3/4 of the bytes, as a safety
    219  // measure.
    220  response = ("a" + "😺".repeat(2048)).repeat(10);
    221 
    222  await request3.get();
    223 
    224  Assert.equal(request3.response.status, 200);
    225 
    226  // Make sure it came through ok, despite the misalignment.
    227  Assert.equal(request3.response.body, response);
    228 
    229  await promiseStopServer(server);
    230 });
    231 
    232 /**
    233 * Test HTTP POST data is encoded as UTF-8 by default.
    234 */
    235 add_task(async function test_post_utf8() {
    236  // We setup a handler that responds with exactly what it received.
    237  // Given we've already tested above that responses are correctly utf-8
    238  // decoded we can surmise that the correct response coming back means the
    239  // input must also have been encoded.
    240  let server = httpd_setup({
    241    "/echo": function (req, res) {
    242      res.setStatusLine(req.httpVersion, 200, "OK");
    243      res.setHeader("Content-Type", req.getHeader("content-type"));
    244      // Get the body as bytes and write them back without touching them
    245      let sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
    246        Ci.nsIScriptableInputStream
    247      );
    248      sis.init(req.bodyInputStream);
    249      let body = sis.read(sis.available());
    250      sis.close();
    251      res.write(body);
    252    },
    253  });
    254 
    255  let data = {
    256    copyright: "©",
    257    // See the comment in test_get_utf8 about this string.
    258    long: ("a" + "😺".repeat(2048)).repeat(10),
    259  };
    260  let request1 = new RESTRequest(server.baseURI + "/echo");
    261  await request1.post(data);
    262 
    263  Assert.equal(request1.response.status, 200);
    264  deepEqual(JSON.parse(request1.response.body), data);
    265  Assert.equal(
    266    request1.response.headers["content-type"],
    267    "application/json; charset=utf-8"
    268  );
    269 
    270  await promiseStopServer(server);
    271 });
    272 
    273 /**
    274 * Test more variations of charset handling.
    275 */
    276 add_task(async function test_charsets() {
    277  let response = "Hello World, I can't speak Russian";
    278 
    279  let contentType = "text/plain";
    280  let charset = true;
    281  let charsetSuffix = "; charset=us-ascii";
    282 
    283  let server = httpd_setup({
    284    "/resource": function (req, res) {
    285      res.setStatusLine(req.httpVersion, 200, "OK");
    286      res.setHeader(
    287        "Content-Type",
    288        contentType + (charset ? charsetSuffix : "")
    289      );
    290 
    291      let converter = Cc[
    292        "@mozilla.org/intl/converter-output-stream;1"
    293      ].createInstance(Ci.nsIConverterOutputStream);
    294      converter.init(res.bodyOutputStream, "us-ascii");
    295      converter.writeString(response);
    296      converter.close();
    297    },
    298  });
    299 
    300  // Check that provided charset overrides hint.
    301  let request1 = new RESTRequest(server.baseURI + "/resource");
    302  request1.charset = "not-a-charset";
    303  await request1.get();
    304  Assert.equal(request1.response.status, 200);
    305  Assert.equal(request1.response.body, response);
    306  Assert.equal(
    307    request1.response.headers["content-type"],
    308    contentType + charsetSuffix
    309  );
    310  Assert.equal(request1.response.charset, "us-ascii");
    311 
    312  // Check that hint is used if Content-Type doesn't have a charset.
    313  charset = false;
    314  let request2 = new RESTRequest(server.baseURI + "/resource");
    315  request2.charset = "us-ascii";
    316  await request2.get();
    317 
    318  Assert.equal(request2.response.status, 200);
    319  Assert.equal(request2.response.body, response);
    320  Assert.equal(request2.response.headers["content-type"], contentType);
    321  Assert.equal(request2.response.charset, "us-ascii");
    322 
    323  await promiseStopServer(server);
    324 });
    325 
    326 /**
    327 * Used for testing PATCH/PUT/POST methods.
    328 */
    329 async function check_posting_data(method) {
    330  let funcName = method.toLowerCase();
    331  let handler = httpd_handler(200, "OK", "Got it!");
    332  let server = httpd_setup({ "/resource": handler });
    333 
    334  let request = new RESTRequest(server.baseURI + "/resource");
    335  Assert.equal(request.status, request.NOT_SENT);
    336  let responsePromise = request[funcName]("Hullo?");
    337  Assert.equal(request.status, request.SENT);
    338  Assert.equal(request.method, method);
    339 
    340  let response = await responsePromise;
    341 
    342  Assert.equal(response, request.response);
    343 
    344  Assert.equal(request.status, request.COMPLETED);
    345  Assert.ok(request.response.success);
    346  Assert.equal(request.response.status, 200);
    347  Assert.equal(request.response.body, "Got it!");
    348 
    349  Assert.equal(handler.request.method, method);
    350  Assert.equal(handler.request.body, "Hullo?");
    351  Assert.equal(handler.request.getHeader("Content-Type"), "text/plain");
    352 
    353  await Assert.rejects(
    354    request[funcName]("Hai!"),
    355    /Request has already been sent/
    356  );
    357 
    358  await promiseStopServer(server);
    359 }
    360 
    361 /**
    362 * Test HTTP PATCH with a simple string argument and default Content-Type.
    363 */
    364 add_task(async function test_patch() {
    365  await check_posting_data("PATCH");
    366 });
    367 
    368 /**
    369 * Test HTTP PUT with a simple string argument and default Content-Type.
    370 */
    371 add_task(async function test_put() {
    372  await check_posting_data("PUT");
    373 });
    374 
    375 /**
    376 * Test HTTP POST with a simple string argument and default Content-Type.
    377 */
    378 add_task(async function test_post() {
    379  await check_posting_data("POST");
    380 });
    381 
    382 /**
    383 * Test HTTP DELETE.
    384 */
    385 add_task(async function test_delete() {
    386  let handler = httpd_handler(200, "OK", "Got it!");
    387  let server = httpd_setup({ "/resource": handler });
    388 
    389  let request = new RESTRequest(server.baseURI + "/resource");
    390  Assert.equal(request.status, request.NOT_SENT);
    391  let responsePromise = request.delete();
    392  Assert.equal(request.status, request.SENT);
    393  Assert.equal(request.method, "DELETE");
    394 
    395  let response = await responsePromise;
    396  Assert.equal(response, request.response);
    397 
    398  Assert.equal(request.status, request.COMPLETED);
    399  Assert.ok(request.response.success);
    400  Assert.equal(request.response.status, 200);
    401  Assert.equal(request.response.body, "Got it!");
    402  Assert.equal(handler.request.method, "DELETE");
    403 
    404  await Assert.rejects(request.delete(), /Request has already been sent/);
    405 
    406  await promiseStopServer(server);
    407 });
    408 
    409 /**
    410 * Test an HTTP response with a non-200 status code.
    411 */
    412 add_task(async function test_get_404() {
    413  let handler = httpd_handler(404, "Not Found", "Cannae find it!");
    414  let server = httpd_setup({ "/resource": handler });
    415 
    416  let request = new RESTRequest(server.baseURI + "/resource");
    417  await request.get();
    418 
    419  Assert.equal(request.status, request.COMPLETED);
    420  Assert.ok(!request.response.success);
    421  Assert.equal(request.response.status, 404);
    422  Assert.equal(request.response.body, "Cannae find it!");
    423 
    424  await promiseStopServer(server);
    425 });
    426 
    427 /**
    428 * The 'data' argument to PUT, if not a string already, is automatically
    429 * stringified as JSON.
    430 */
    431 add_task(async function test_put_json() {
    432  let handler = httpd_handler(200, "OK");
    433  let server = httpd_setup({ "/resource": handler });
    434 
    435  let sample_data = {
    436    some: "sample_data",
    437    injson: "format",
    438    number: 42,
    439  };
    440  let request = new RESTRequest(server.baseURI + "/resource");
    441  await request.put(sample_data);
    442 
    443  Assert.equal(request.status, request.COMPLETED);
    444  Assert.ok(request.response.success);
    445  Assert.equal(request.response.status, 200);
    446  Assert.equal(request.response.body, "");
    447 
    448  Assert.equal(handler.request.method, "PUT");
    449  Assert.equal(handler.request.body, JSON.stringify(sample_data));
    450  Assert.equal(
    451    handler.request.getHeader("Content-Type"),
    452    "application/json; charset=utf-8"
    453  );
    454 
    455  await promiseStopServer(server);
    456 });
    457 
    458 /**
    459 * The 'data' argument to POST, if not a string already, is automatically
    460 * stringified as JSON.
    461 */
    462 add_task(async function test_post_json() {
    463  let handler = httpd_handler(200, "OK");
    464  let server = httpd_setup({ "/resource": handler });
    465 
    466  let sample_data = {
    467    some: "sample_data",
    468    injson: "format",
    469    number: 42,
    470  };
    471  let request = new RESTRequest(server.baseURI + "/resource");
    472  await request.post(sample_data);
    473 
    474  Assert.equal(request.status, request.COMPLETED);
    475  Assert.ok(request.response.success);
    476  Assert.equal(request.response.status, 200);
    477  Assert.equal(request.response.body, "");
    478 
    479  Assert.equal(handler.request.method, "POST");
    480  Assert.equal(handler.request.body, JSON.stringify(sample_data));
    481  Assert.equal(
    482    handler.request.getHeader("Content-Type"),
    483    "application/json; charset=utf-8"
    484  );
    485 
    486  await promiseStopServer(server);
    487 });
    488 
    489 /**
    490 * The content-type will be text/plain without a charset if the 'data' argument
    491 * to POST is already a string.
    492 */
    493 add_task(async function test_post_json() {
    494  let handler = httpd_handler(200, "OK");
    495  let server = httpd_setup({ "/resource": handler });
    496 
    497  let sample_data = "hello";
    498  let request = new RESTRequest(server.baseURI + "/resource");
    499  await request.post(sample_data);
    500  Assert.equal(request.status, request.COMPLETED);
    501  Assert.ok(request.response.success);
    502  Assert.equal(request.response.status, 200);
    503  Assert.equal(request.response.body, "");
    504 
    505  Assert.equal(handler.request.method, "POST");
    506  Assert.equal(handler.request.body, sample_data);
    507  Assert.equal(handler.request.getHeader("Content-Type"), "text/plain");
    508 
    509  await promiseStopServer(server);
    510 });
    511 
    512 /**
    513 * HTTP PUT with a custom Content-Type header.
    514 */
    515 add_task(async function test_put_override_content_type() {
    516  let handler = httpd_handler(200, "OK");
    517  let server = httpd_setup({ "/resource": handler });
    518 
    519  let request = new RESTRequest(server.baseURI + "/resource");
    520  request.setHeader("Content-Type", "application/lolcat");
    521  await request.put("O HAI!!1!");
    522 
    523  Assert.equal(request.status, request.COMPLETED);
    524  Assert.ok(request.response.success);
    525  Assert.equal(request.response.status, 200);
    526  Assert.equal(request.response.body, "");
    527 
    528  Assert.equal(handler.request.method, "PUT");
    529  Assert.equal(handler.request.body, "O HAI!!1!");
    530  Assert.equal(handler.request.getHeader("Content-Type"), "application/lolcat");
    531 
    532  await promiseStopServer(server);
    533 });
    534 
    535 /**
    536 * HTTP POST with a custom Content-Type header.
    537 */
    538 add_task(async function test_post_override_content_type() {
    539  let handler = httpd_handler(200, "OK");
    540  let server = httpd_setup({ "/resource": handler });
    541 
    542  let request = new RESTRequest(server.baseURI + "/resource");
    543  request.setHeader("Content-Type", "application/lolcat");
    544  await request.post("O HAI!!1!");
    545 
    546  Assert.equal(request.status, request.COMPLETED);
    547  Assert.ok(request.response.success);
    548  Assert.equal(request.response.status, 200);
    549  Assert.equal(request.response.body, "");
    550 
    551  Assert.equal(handler.request.method, "POST");
    552  Assert.equal(handler.request.body, "O HAI!!1!");
    553  Assert.equal(handler.request.getHeader("Content-Type"), "application/lolcat");
    554 
    555  await promiseStopServer(server);
    556 });
    557 
    558 /**
    559 * No special headers are sent by default on a GET request.
    560 */
    561 add_task(async function test_get_no_headers() {
    562  let handler = httpd_handler(200, "OK");
    563  let server = httpd_setup({ "/resource": handler });
    564 
    565  let ignore_headers = [
    566    "host",
    567    "user-agent",
    568    "accept",
    569    "accept-language",
    570    "accept-encoding",
    571    "accept-charset",
    572    "keep-alive",
    573    "connection",
    574    "pragma",
    575    "cache-control",
    576    "content-length",
    577    "sec-fetch-dest",
    578    "sec-fetch-mode",
    579    "sec-fetch-site",
    580    "sec-fetch-user",
    581    "priority",
    582  ];
    583  let request = new RESTRequest(server.baseURI + "/resource");
    584  await request.get();
    585 
    586  Assert.equal(request.response.status, 200);
    587  Assert.equal(request.response.body, "");
    588 
    589  let server_headers = handler.request.headers;
    590  while (server_headers.hasMoreElements()) {
    591    let header = server_headers.getNext().toString();
    592    if (!ignore_headers.includes(header)) {
    593      do_throw("Got unexpected header!");
    594    }
    595  }
    596 
    597  await promiseStopServer(server);
    598 });
    599 
    600 /**
    601 * Client includes default Accept header in API requests
    602 */
    603 add_task(async function test_default_accept_headers() {
    604  let handler = httpd_handler(200, "OK");
    605  let server = httpd_setup({ "/resource": handler });
    606 
    607  let request = new RESTRequest(server.baseURI + "/resource");
    608  await request.get();
    609 
    610  Assert.equal(request.response.status, 200);
    611  Assert.equal(request.response.body, "");
    612 
    613  let accept_header = handler.request.getHeader("accept");
    614 
    615  Assert.ok(!accept_header.includes("text/html"));
    616  Assert.ok(!accept_header.includes("application/xhtml+xml"));
    617  Assert.ok(!accept_header.includes("applcation/xml"));
    618 
    619  Assert.ok(
    620    accept_header.includes("application/json") ||
    621      accept_header.includes("application/newlines")
    622  );
    623 
    624  await promiseStopServer(server);
    625 });
    626 
    627 /**
    628 * Test changing the URI after having created the request.
    629 */
    630 add_task(async function test_changing_uri() {
    631  let handler = httpd_handler(200, "OK");
    632  let server = httpd_setup({ "/resource": handler });
    633 
    634  let request = new RESTRequest("http://localhost:1234/the-wrong-resource");
    635  request.uri = CommonUtils.makeURI(server.baseURI + "/resource");
    636  let response = await request.get();
    637  Assert.equal(response.status, 200);
    638  await promiseStopServer(server);
    639 });
    640 
    641 /**
    642 * Test setting HTTP request headers.
    643 */
    644 add_task(async function test_request_setHeader() {
    645  let handler = httpd_handler(200, "OK");
    646  let server = httpd_setup({ "/resource": handler });
    647 
    648  let request = new RESTRequest(server.baseURI + "/resource");
    649 
    650  request.setHeader("X-What-Is-Weave", "awesome");
    651  request.setHeader("X-WHAT-is-Weave", "more awesomer");
    652  request.setHeader("Another-Header", "Hello World");
    653  await request.get();
    654 
    655  Assert.equal(request.response.status, 200);
    656  Assert.equal(request.response.body, "");
    657 
    658  Assert.equal(handler.request.getHeader("X-What-Is-Weave"), "more awesomer");
    659  Assert.equal(handler.request.getHeader("another-header"), "Hello World");
    660 
    661  await promiseStopServer(server);
    662 });
    663 
    664 /**
    665 * Test receiving HTTP response headers.
    666 */
    667 add_task(async function test_response_headers() {
    668  function handler(request, response) {
    669    response.setHeader("X-What-Is-Weave", "awesome");
    670    response.setHeader("Another-Header", "Hello World");
    671    response.setStatusLine(request.httpVersion, 200, "OK");
    672  }
    673  let server = httpd_setup({ "/resource": handler });
    674  let request = new RESTRequest(server.baseURI + "/resource");
    675  await request.get();
    676 
    677  Assert.equal(request.response.status, 200);
    678  Assert.equal(request.response.body, "");
    679 
    680  Assert.equal(request.response.headers["x-what-is-weave"], "awesome");
    681  Assert.equal(request.response.headers["another-header"], "Hello World");
    682 
    683  await promiseStopServer(server);
    684 });
    685 
    686 /**
    687 * The onComplete() handler gets called in case of any network errors
    688 * (e.g. NS_ERROR_CONNECTION_REFUSED).
    689 */
    690 add_task(async function test_connection_refused() {
    691  let request = new RESTRequest("http://localhost:1234/resource");
    692 
    693  // Fail the test if we resolve, return the error if we reject
    694  await Assert.rejects(
    695    request.get(),
    696    error =>
    697      error.result == Cr.NS_ERROR_CONNECTION_REFUSED &&
    698      error.message == "NS_ERROR_CONNECTION_REFUSED"
    699  );
    700 
    701  Assert.equal(request.status, request.COMPLETED);
    702 });
    703 
    704 /**
    705 * Abort a request that just sent off.
    706 */
    707 add_task(async function test_abort() {
    708  function handler() {
    709    do_throw("Shouldn't have gotten here!");
    710  }
    711  let server = httpd_setup({ "/resource": handler });
    712 
    713  let request = new RESTRequest(server.baseURI + "/resource");
    714 
    715  // Aborting a request that hasn't been sent yet is pointless and will throw.
    716  do_check_throws(function () {
    717    request.abort();
    718  });
    719 
    720  let responsePromise = request.get();
    721  request.abort();
    722 
    723  // Aborting an already aborted request is pointless and will throw.
    724  do_check_throws(function () {
    725    request.abort();
    726  });
    727 
    728  Assert.equal(request.status, request.ABORTED);
    729 
    730  await Assert.rejects(responsePromise, /NS_BINDING_ABORTED/);
    731 
    732  await promiseStopServer(server);
    733 });
    734 
    735 /**
    736 * A non-zero 'timeout' property specifies the amount of seconds to wait after
    737 * channel activity until the request is automatically canceled.
    738 */
    739 add_task(async function test_timeout() {
    740  let server = new HttpServer();
    741  let server_connection;
    742  server._handler.handleResponse = function (connection) {
    743    // This is a handler that doesn't do anything, just keeps the connection
    744    // open, thereby mimicking a timing out connection. We keep a reference to
    745    // the open connection for later so it can be properly disposed of. That's
    746    // why you really only want to make one HTTP request to this server ever.
    747    server_connection = connection;
    748  };
    749  server.start();
    750  let identity = server.identity;
    751  let uri =
    752    identity.primaryScheme +
    753    "://" +
    754    identity.primaryHost +
    755    ":" +
    756    identity.primaryPort;
    757 
    758  let request = new RESTRequest(uri + "/resource");
    759  request.timeout = 0.1; // 100 milliseconds
    760 
    761  await Assert.rejects(
    762    request.get(),
    763    error => error.result == Cr.NS_ERROR_NET_TIMEOUT
    764  );
    765 
    766  Assert.equal(request.status, request.ABORTED);
    767 
    768  // server_connection is undefined on the Android emulator for reasons
    769  // unknown. Yet, we still get here. If this test is refactored, we should
    770  // investigate the reason why the above callback is behaving differently.
    771  if (server_connection) {
    772    _("Closing connection.");
    773    server_connection.close();
    774  }
    775  await promiseStopServer(server);
    776 });
    777 
    778 add_task(async function test_new_channel() {
    779  _("Ensure a redirect to a new channel is handled properly.");
    780 
    781  function checkUA(metadata) {
    782    let ua = metadata.getHeader("User-Agent");
    783    _("User-Agent is " + ua);
    784    Assert.equal("foo bar", ua);
    785  }
    786 
    787  let redirectRequested = false;
    788  let redirectURL;
    789  function redirectHandler(metadata, response) {
    790    checkUA(metadata);
    791    redirectRequested = true;
    792 
    793    let body = "Redirecting";
    794    response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT");
    795    response.setHeader("Location", redirectURL);
    796    response.bodyOutputStream.write(body, body.length);
    797  }
    798 
    799  let resourceRequested = false;
    800  function resourceHandler(metadata, response) {
    801    checkUA(metadata);
    802    resourceRequested = true;
    803 
    804    let body = "Test";
    805    response.setHeader("Content-Type", "text/plain");
    806    response.bodyOutputStream.write(body, body.length);
    807  }
    808 
    809  let server1 = httpd_setup({ "/redirect": redirectHandler });
    810  let server2 = httpd_setup({ "/resource": resourceHandler });
    811  redirectURL = server2.baseURI + "/resource";
    812 
    813  let request = new RESTRequest(server1.baseURI + "/redirect");
    814  request.setHeader("User-Agent", "foo bar");
    815 
    816  // Swizzle in our own fakery, because this redirect is neither
    817  // internal nor URI-preserving. RESTRequest's policy is to only
    818  // copy headers under certain circumstances.
    819  let protoMethod = request.shouldCopyOnRedirect;
    820  request.shouldCopyOnRedirect = function wrapped(o, n, f) {
    821    // Check the default policy.
    822    Assert.ok(!protoMethod.call(this, o, n, f));
    823    return true;
    824  };
    825 
    826  let response = await request.get();
    827 
    828  Assert.equal(200, response.status);
    829  Assert.equal("Test", response.body);
    830  Assert.ok(redirectRequested);
    831  Assert.ok(resourceRequested);
    832 
    833  await promiseStopServer(server1);
    834  await promiseStopServer(server2);
    835 });
    836 
    837 add_task(async function test_not_sending_cookie() {
    838  function handler(metadata, response) {
    839    let body = "COOKIE!";
    840    response.setStatusLine(metadata.httpVersion, 200, "OK");
    841    response.bodyOutputStream.write(body, body.length);
    842    Assert.ok(!metadata.hasHeader("Cookie"));
    843  }
    844  let server = httpd_setup({ "/test": handler });
    845 
    846  let uri = CommonUtils.makeURI(server.baseURI);
    847  let channel = NetUtil.newChannel({
    848    uri,
    849    loadUsingSystemPrincipal: true,
    850    contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
    851  });
    852  Services.cookies.setCookieStringFromHttp(uri, "test=test; path=/;", channel);
    853 
    854  let res = new RESTRequest(server.baseURI + "/test");
    855  let response = await res.get();
    856 
    857  Assert.ok(response.success);
    858  Assert.equal("COOKIE!", response.body);
    859 
    860  await promiseStopServer(server);
    861 });