11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  hasCrypto,
51cb0ef41Sopenharmony_ci  mustCall,
61cb0ef41Sopenharmony_ci  mustNotCall,
71cb0ef41Sopenharmony_ci  skip
81cb0ef41Sopenharmony_ci} = require('../common');
91cb0ef41Sopenharmony_ciif (!hasCrypto)
101cb0ef41Sopenharmony_ci  skip('missing crypto');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst {
131cb0ef41Sopenharmony_ci  deepStrictEqual,
141cb0ef41Sopenharmony_ci  strictEqual,
151cb0ef41Sopenharmony_ci  throws
161cb0ef41Sopenharmony_ci} = require('assert');
171cb0ef41Sopenharmony_ciconst {
181cb0ef41Sopenharmony_ci  createSecureServer,
191cb0ef41Sopenharmony_ci  createServer,
201cb0ef41Sopenharmony_ci  connect
211cb0ef41Sopenharmony_ci} = require('http2');
221cb0ef41Sopenharmony_ciconst Countdown = require('../common/countdown');
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciconst { readKey } = require('../common/fixtures');
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciconst key = readKey('agent8-key.pem', 'binary');
271cb0ef41Sopenharmony_ciconst cert = readKey('agent8-cert.pem', 'binary');
281cb0ef41Sopenharmony_ciconst ca = readKey('fake-startcom-root-cert.pem', 'binary');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci{
311cb0ef41Sopenharmony_ci  const server = createSecureServer({ key, cert });
321cb0ef41Sopenharmony_ci  server.on('stream', mustCall((stream) => {
331cb0ef41Sopenharmony_ci    stream.session.origin('https://example.org/a/b/c',
341cb0ef41Sopenharmony_ci                          new URL('https://example.com'));
351cb0ef41Sopenharmony_ci    stream.respond();
361cb0ef41Sopenharmony_ci    stream.end('ok');
371cb0ef41Sopenharmony_ci  }));
381cb0ef41Sopenharmony_ci  server.on('session', mustCall((session) => {
391cb0ef41Sopenharmony_ci    session.origin('https://foo.org/a/b/c', new URL('https://bar.org'));
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    // Won't error, but won't send anything
421cb0ef41Sopenharmony_ci    session.origin();
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci    [0, true, {}, []].forEach((input) => {
451cb0ef41Sopenharmony_ci      throws(
461cb0ef41Sopenharmony_ci        () => session.origin(input),
471cb0ef41Sopenharmony_ci        {
481cb0ef41Sopenharmony_ci          code: 'ERR_INVALID_ARG_TYPE',
491cb0ef41Sopenharmony_ci          name: 'TypeError'
501cb0ef41Sopenharmony_ci        }
511cb0ef41Sopenharmony_ci      );
521cb0ef41Sopenharmony_ci    });
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    [new URL('foo://bar'), 'foo://bar'].forEach((input) => {
551cb0ef41Sopenharmony_ci      throws(
561cb0ef41Sopenharmony_ci        () => session.origin(input),
571cb0ef41Sopenharmony_ci        {
581cb0ef41Sopenharmony_ci          code: 'ERR_HTTP2_INVALID_ORIGIN',
591cb0ef41Sopenharmony_ci          name: 'TypeError'
601cb0ef41Sopenharmony_ci        }
611cb0ef41Sopenharmony_ci      );
621cb0ef41Sopenharmony_ci    });
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    ['not a valid url'].forEach((input) => {
651cb0ef41Sopenharmony_ci      throws(
661cb0ef41Sopenharmony_ci        () => session.origin(input),
671cb0ef41Sopenharmony_ci        {
681cb0ef41Sopenharmony_ci          code: 'ERR_INVALID_URL',
691cb0ef41Sopenharmony_ci          name: 'TypeError'
701cb0ef41Sopenharmony_ci        }
711cb0ef41Sopenharmony_ci      );
721cb0ef41Sopenharmony_ci    });
731cb0ef41Sopenharmony_ci    const longInput = `http://foo.bar${'a'.repeat(16383)}`;
741cb0ef41Sopenharmony_ci    throws(
751cb0ef41Sopenharmony_ci      () => session.origin(longInput),
761cb0ef41Sopenharmony_ci      {
771cb0ef41Sopenharmony_ci        code: 'ERR_HTTP2_ORIGIN_LENGTH',
781cb0ef41Sopenharmony_ci        name: 'TypeError'
791cb0ef41Sopenharmony_ci      }
801cb0ef41Sopenharmony_ci    );
811cb0ef41Sopenharmony_ci  }));
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
841cb0ef41Sopenharmony_ci    const originSet = [`https://localhost:${server.address().port}`];
851cb0ef41Sopenharmony_ci    const client = connect(originSet[0], { ca });
861cb0ef41Sopenharmony_ci    const checks = [
871cb0ef41Sopenharmony_ci      ['https://foo.org', 'https://bar.org'],
881cb0ef41Sopenharmony_ci      ['https://example.org', 'https://example.com'],
891cb0ef41Sopenharmony_ci    ];
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci    const countdown = new Countdown(3, () => {
921cb0ef41Sopenharmony_ci      client.close();
931cb0ef41Sopenharmony_ci      server.close();
941cb0ef41Sopenharmony_ci    });
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci    client.on('origin', mustCall((origins) => {
971cb0ef41Sopenharmony_ci      const check = checks.shift();
981cb0ef41Sopenharmony_ci      originSet.push(...check);
991cb0ef41Sopenharmony_ci      deepStrictEqual(client.originSet, originSet);
1001cb0ef41Sopenharmony_ci      deepStrictEqual(origins, check);
1011cb0ef41Sopenharmony_ci      countdown.dec();
1021cb0ef41Sopenharmony_ci    }, 2));
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    client.request().on('close', mustCall(() => countdown.dec())).resume();
1051cb0ef41Sopenharmony_ci  }));
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci// Test automatically sending origin on connection start
1091cb0ef41Sopenharmony_ci{
1101cb0ef41Sopenharmony_ci  const origins = ['https://foo.org/a/b/c', 'https://bar.org'];
1111cb0ef41Sopenharmony_ci  const server = createSecureServer({ key, cert, origins });
1121cb0ef41Sopenharmony_ci  server.on('stream', mustCall((stream) => {
1131cb0ef41Sopenharmony_ci    stream.respond();
1141cb0ef41Sopenharmony_ci    stream.end('ok');
1151cb0ef41Sopenharmony_ci  }));
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1181cb0ef41Sopenharmony_ci    const check = ['https://foo.org', 'https://bar.org'];
1191cb0ef41Sopenharmony_ci    const originSet = [`https://localhost:${server.address().port}`];
1201cb0ef41Sopenharmony_ci    const client = connect(originSet[0], { ca });
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci    const countdown = new Countdown(2, () => {
1231cb0ef41Sopenharmony_ci      client.close();
1241cb0ef41Sopenharmony_ci      server.close();
1251cb0ef41Sopenharmony_ci    });
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci    client.on('origin', mustCall((origins) => {
1281cb0ef41Sopenharmony_ci      originSet.push(...check);
1291cb0ef41Sopenharmony_ci      deepStrictEqual(client.originSet, originSet);
1301cb0ef41Sopenharmony_ci      deepStrictEqual(origins, check);
1311cb0ef41Sopenharmony_ci      countdown.dec();
1321cb0ef41Sopenharmony_ci    }));
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci    client.request().on('close', mustCall(() => countdown.dec())).resume();
1351cb0ef41Sopenharmony_ci  }));
1361cb0ef41Sopenharmony_ci}
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci// If return status is 421, the request origin must be removed from the
1391cb0ef41Sopenharmony_ci// originSet
1401cb0ef41Sopenharmony_ci{
1411cb0ef41Sopenharmony_ci  const server = createSecureServer({ key, cert });
1421cb0ef41Sopenharmony_ci  server.on('stream', mustCall((stream) => {
1431cb0ef41Sopenharmony_ci    stream.respond({ ':status': 421 });
1441cb0ef41Sopenharmony_ci    stream.end();
1451cb0ef41Sopenharmony_ci  }));
1461cb0ef41Sopenharmony_ci  server.on('session', mustCall((session) => {
1471cb0ef41Sopenharmony_ci    session.origin('https://foo.org');
1481cb0ef41Sopenharmony_ci  }));
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1511cb0ef41Sopenharmony_ci    const origin = `https://localhost:${server.address().port}`;
1521cb0ef41Sopenharmony_ci    const client = connect(origin, { ca });
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci    client.on('origin', mustCall((origins) => {
1551cb0ef41Sopenharmony_ci      deepStrictEqual(client.originSet, [origin, 'https://foo.org']);
1561cb0ef41Sopenharmony_ci      const req = client.request({ ':authority': 'foo.org' });
1571cb0ef41Sopenharmony_ci      req.on('response', mustCall((headers) => {
1581cb0ef41Sopenharmony_ci        strictEqual(headers[':status'], 421);
1591cb0ef41Sopenharmony_ci        deepStrictEqual(client.originSet, [origin]);
1601cb0ef41Sopenharmony_ci      }));
1611cb0ef41Sopenharmony_ci      req.resume();
1621cb0ef41Sopenharmony_ci      req.on('close', mustCall(() => {
1631cb0ef41Sopenharmony_ci        client.close();
1641cb0ef41Sopenharmony_ci        server.close();
1651cb0ef41Sopenharmony_ci      }));
1661cb0ef41Sopenharmony_ci    }, 1));
1671cb0ef41Sopenharmony_ci  }));
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci// Origin is ignored on plain text HTTP/2 connections... server will still
1711cb0ef41Sopenharmony_ci// send them, but client will ignore them.
1721cb0ef41Sopenharmony_ci{
1731cb0ef41Sopenharmony_ci  const server = createServer();
1741cb0ef41Sopenharmony_ci  server.on('stream', mustCall((stream) => {
1751cb0ef41Sopenharmony_ci    stream.session.origin('https://example.org',
1761cb0ef41Sopenharmony_ci                          new URL('https://example.com'));
1771cb0ef41Sopenharmony_ci    stream.respond();
1781cb0ef41Sopenharmony_ci    stream.end('ok');
1791cb0ef41Sopenharmony_ci  }));
1801cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1811cb0ef41Sopenharmony_ci    const client = connect(`http://localhost:${server.address().port}`);
1821cb0ef41Sopenharmony_ci    client.on('origin', mustNotCall());
1831cb0ef41Sopenharmony_ci    strictEqual(client.originSet, undefined);
1841cb0ef41Sopenharmony_ci    const req = client.request();
1851cb0ef41Sopenharmony_ci    req.resume();
1861cb0ef41Sopenharmony_ci    req.on('close', mustCall(() => {
1871cb0ef41Sopenharmony_ci      client.close();
1881cb0ef41Sopenharmony_ci      server.close();
1891cb0ef41Sopenharmony_ci    }));
1901cb0ef41Sopenharmony_ci  }));
1911cb0ef41Sopenharmony_ci}
192