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