• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2
3'use strict';
4
5const common = require('../common');
6
7if (!common.hasCrypto)
8  common.skip('missing crypto');
9
10const assert = require('assert');
11const fixtures = require('../common/fixtures');
12const h2 = require('http2');
13const { kSocket } = require('internal/http2/util');
14const tls = require('tls');
15
16function loadKey(keyname) {
17  return fixtures.readKey(keyname, 'binary');
18}
19
20function onStream(stream, headers) {
21  const socket = stream.session[kSocket];
22
23  assert(stream.session.encrypted);
24  assert.strictEqual(stream.session.alpnProtocol, 'h2');
25  const originSet = stream.session.originSet;
26  assert(Array.isArray(originSet));
27  assert.strictEqual(originSet[0],
28                     `https://${socket.servername}:${socket.remotePort}`);
29
30  assert(headers[':authority'].startsWith(socket.servername));
31  stream.respond({ 'content-type': 'application/json' });
32  stream.end(JSON.stringify({
33    servername: socket.servername,
34    alpnProtocol: socket.alpnProtocol
35  }));
36}
37
38function verifySecureSession(key, cert, ca, opts) {
39  const server = h2.createSecureServer({ cert, key });
40  server.on('stream', common.mustCall(onStream));
41  server.on('close', common.mustCall());
42  server.listen(0, common.mustCall(() => {
43    opts = opts || { };
44    opts.secureContext = tls.createSecureContext({ ca });
45    const client = h2.connect(`https://localhost:${server.address().port}`,
46                              opts);
47    // Verify that a 'secureConnect' listener is attached
48    assert.strictEqual(client.socket.listenerCount('secureConnect'), 1);
49    const req = client.request();
50
51    client.on('connect', common.mustCall(() => {
52      assert(client.encrypted);
53      assert.strictEqual(client.alpnProtocol, 'h2');
54      const originSet = client.originSet;
55      assert(Array.isArray(originSet));
56      assert.strictEqual(originSet.length, 1);
57      assert.strictEqual(
58        originSet[0],
59        `https://${opts.servername || 'localhost'}:${server.address().port}`);
60    }));
61
62    req.on('response', common.mustCall((headers) => {
63      assert.strictEqual(headers[':status'], 200);
64      assert.strictEqual(headers['content-type'], 'application/json');
65      assert(headers.date);
66    }));
67
68    let data = '';
69    req.setEncoding('utf8');
70    req.on('data', (d) => data += d);
71    req.on('end', common.mustCall(() => {
72      const jsonData = JSON.parse(data);
73      assert.strictEqual(jsonData.servername,
74                         opts.servername || 'localhost');
75      assert.strictEqual(jsonData.alpnProtocol, 'h2');
76      server.close(common.mustSucceed());
77      client[kSocket].destroy();
78    }));
79  }));
80}
81
82// The server can be connected as 'localhost'.
83verifySecureSession(
84  loadKey('agent8-key.pem'),
85  loadKey('agent8-cert.pem'),
86  loadKey('fake-startcom-root-cert.pem'));
87
88// Custom servername is specified.
89verifySecureSession(
90  loadKey('agent1-key.pem'),
91  loadKey('agent1-cert.pem'),
92  loadKey('ca1-cert.pem'),
93  { servername: 'agent1' });
94