tor-browser

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

test_bhttp.js (6498B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Unit tests for the binary http bindings.
      7 // Tests basic encoding and decoding of requests and responses.
      8 
      9 function BinaryHttpRequest(
     10  method,
     11  scheme,
     12  authority,
     13  path,
     14  headerNames,
     15  headerValues,
     16  content
     17 ) {
     18  this.method = method;
     19  this.scheme = scheme;
     20  this.authority = authority;
     21  this.path = path;
     22  this.headerNames = headerNames;
     23  this.headerValues = headerValues;
     24  this.content = content;
     25 }
     26 
     27 BinaryHttpRequest.prototype = {
     28  QueryInterface: ChromeUtils.generateQI(["nsIBinaryHttpRequest"]),
     29 };
     30 
     31 function test_encode_request() {
     32  let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
     33    Ci.nsIBinaryHttp
     34  );
     35  let request = new BinaryHttpRequest(
     36    "GET",
     37    "https",
     38    "",
     39    "/hello.txt",
     40    ["user-agent", "host", "accept-language"],
     41    [
     42      "curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3",
     43      "www.example.com",
     44      "en, mi",
     45    ],
     46    []
     47  );
     48  let encoded = bhttp.encodeRequest(request);
     49  // This example is from RFC 9292.
     50  let expected = hexStringToBytes(
     51    "0003474554056874747073000a2f6865" +
     52      "6c6c6f2e747874406c0a757365722d61" +
     53      "67656e74346375726c2f372e31362e33" +
     54      "206c69626375726c2f372e31362e3320" +
     55      "4f70656e53534c2f302e392e376c207a" +
     56      "6c69622f312e322e3304686f73740f77" +
     57      "77772e6578616d706c652e636f6d0f61" +
     58      "63636570742d6c616e67756167650665" +
     59      "6e2c206d690000"
     60  );
     61  deepEqual(encoded, expected);
     62 
     63  let mismatchedHeaders = new BinaryHttpRequest(
     64    "GET",
     65    "https",
     66    "",
     67    "",
     68    ["whoops-only-one-header-name"],
     69    ["some-header-value", "some-other-header-value"],
     70    []
     71  );
     72  // The implementation uses "NS_ERROR_INVALID_ARG", because that's an
     73  // appropriate description for the error.  However, that is an alias to
     74  // "NS_ERROR_ILLEGAL_VALUE", which is what the actual exception uses, so
     75  // that's what is tested for here.
     76  Assert.throws(
     77    () => bhttp.encodeRequest(mismatchedHeaders),
     78    /NS_ERROR_ILLEGAL_VALUE/
     79  );
     80 }
     81 
     82 function test_decode_request() {
     83  let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
     84    Ci.nsIBinaryHttp
     85  );
     86 
     87  // From RFC 9292.
     88  let encoded = hexStringToBytes(
     89    "0003474554056874747073000a2f6865" +
     90      "6c6c6f2e747874406c0a757365722d61" +
     91      "67656e74346375726c2f372e31362e33" +
     92      "206c69626375726c2f372e31362e3320" +
     93      "4f70656e53534c2f302e392e376c207a" +
     94      "6c69622f312e322e3304686f73740f77" +
     95      "77772e6578616d706c652e636f6d0f61" +
     96      "63636570742d6c616e67756167650665" +
     97      "6e2c206d690000"
     98  );
     99  let request = bhttp.decodeRequest(encoded);
    100  equal(request.method, "GET");
    101  equal(request.scheme, "https");
    102  equal(request.authority, "");
    103  equal(request.path, "/hello.txt");
    104  let expectedHeaderNames = ["user-agent", "host", "accept-language"];
    105  deepEqual(request.headerNames, expectedHeaderNames);
    106  let expectedHeaderValues = [
    107    "curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3",
    108    "www.example.com",
    109    "en, mi",
    110  ];
    111  deepEqual(request.headerValues, expectedHeaderValues);
    112  deepEqual(request.content, []);
    113 
    114  let garbage = hexStringToBytes("115f00ab64c0fa783fe4cb723eaa87fa78900a0b00");
    115  Assert.throws(() => bhttp.decodeRequest(garbage), /NS_ERROR_UNEXPECTED/);
    116 }
    117 
    118 function test_decode_response() {
    119  let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
    120    Ci.nsIBinaryHttp
    121  );
    122  // From RFC 9292.
    123  let encoded = hexStringToBytes(
    124    "0340660772756e6e696e670a22736c65" +
    125      "657020313522004067046c696e6b233c" +
    126      "2f7374796c652e6373733e3b2072656c" +
    127      "3d7072656c6f61643b2061733d737479" +
    128      "6c65046c696e6b243c2f736372697074" +
    129      "2e6a733e3b2072656c3d7072656c6f61" +
    130      "643b2061733d7363726970740040c804" +
    131      "646174651d4d6f6e2c203237204a756c" +
    132      "20323030392031323a32383a35332047" +
    133      "4d540673657276657206417061636865" +
    134      "0d6c6173742d6d6f6469666965641d57" +
    135      "65642c203232204a756c203230303920" +
    136      "31393a31353a353620474d5404657461" +
    137      "671422333461613338372d642d313536" +
    138      "3865623030220d6163636570742d7261" +
    139      "6e6765730562797465730e636f6e7465" +
    140      "6e742d6c656e67746802353104766172" +
    141      "790f4163636570742d456e636f64696e" +
    142      "670c636f6e74656e742d747970650a74" +
    143      "6578742f706c61696e003348656c6c6f" +
    144      "20576f726c6421204d7920636f6e7465" +
    145      "6e7420696e636c756465732061207472" +
    146      "61696c696e672043524c462e0d0a0000"
    147  );
    148  let response = bhttp.decodeResponse(encoded);
    149  equal(response.status, 200);
    150  deepEqual(
    151    response.content,
    152    stringToBytes("Hello World! My content includes a trailing CRLF.\r\n")
    153  );
    154  let expectedHeaderNames = [
    155    "date",
    156    "server",
    157    "last-modified",
    158    "etag",
    159    "accept-ranges",
    160    "content-length",
    161    "vary",
    162    "content-type",
    163  ];
    164  deepEqual(response.headerNames, expectedHeaderNames);
    165  let expectedHeaderValues = [
    166    "Mon, 27 Jul 2009 12:28:53 GMT",
    167    "Apache",
    168    "Wed, 22 Jul 2009 19:15:56 GMT",
    169    '"34aa387-d-1568eb00"',
    170    "bytes",
    171    "51",
    172    "Accept-Encoding",
    173    "text/plain",
    174  ];
    175  deepEqual(response.headerValues, expectedHeaderValues);
    176 
    177  let garbage = hexStringToBytes(
    178    "0367890084cb0ab03115fa0b4c2ea0fa783f7a87fa00"
    179  );
    180  Assert.throws(() => bhttp.decodeResponse(garbage), /NS_ERROR_UNEXPECTED/);
    181 }
    182 
    183 function test_encode_response() {
    184  let response = new BinaryHttpResponse(
    185    418,
    186    ["content-type"],
    187    ["text/plain"],
    188    stringToBytes("I'm a teapot")
    189  );
    190  let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
    191    Ci.nsIBinaryHttp
    192  );
    193  let encoded = bhttp.encodeResponse(response);
    194  let expected = hexStringToBytes(
    195    "0141a2180c636f6e74656e742d747970650a746578742f706c61696e0c49276d206120746561706f7400"
    196  );
    197  deepEqual(encoded, expected);
    198 
    199  let mismatchedHeaders = new BinaryHttpResponse(
    200    500,
    201    ["some-header", "some-other-header"],
    202    ["whoops-only-one-header-value"],
    203    []
    204  );
    205  // The implementation uses "NS_ERROR_INVALID_ARG", because that's an
    206  // appropriate description for the error.  However, that is an alias to
    207  // "NS_ERROR_ILLEGAL_VALUE", which is what the actual exception uses, so
    208  // that's what is tested for here.
    209  Assert.throws(
    210    () => bhttp.encodeResponse(mismatchedHeaders),
    211    /NS_ERROR_ILLEGAL_VALUE/
    212  );
    213 }
    214 
    215 function run_test() {
    216  test_encode_request();
    217  test_decode_request();
    218  test_encode_response();
    219  test_decode_response();
    220 }