1// Flags: --expose-internals 2 3'use strict'; 4 5const common = require('../common'); 6if (!common.hasCrypto) 7 common.skip('missing crypto'); 8const assert = require('assert'); 9const h2 = require('http2'); 10const { kSocket } = require('internal/http2/util'); 11const { once } = require('events'); 12 13const server = h2.createServer(); 14 15// We use the lower-level API here 16server.on('stream', common.mustCall(onStream)); 17 18function onStream(stream) { 19 stream.respond(); 20 stream.write('test'); 21 22 const socket = stream.session[kSocket]; 23 24 // When the socket is destroyed, the close events must be triggered 25 // on the socket, server and session. 26 socket.on('close', common.mustCall()); 27 stream.on('close', common.mustCall()); 28 server.on('close', common.mustCall()); 29 stream.session.on('close', common.mustCall(() => server.close())); 30 31 // Also, the aborted event must be triggered on the stream 32 stream.on('aborted', common.mustCall()); 33 34 assert.notStrictEqual(stream.session, undefined); 35 socket.destroy(); 36} 37 38server.listen(0); 39 40server.on('listening', common.mustCall(async () => { 41 const client = h2.connect(`http://localhost:${server.address().port}`); 42 // The client may have an ECONNRESET error here depending on the operating 43 // system, due mainly to differences in the timing of socket closing. Do 44 // not wrap this in a common mustCall. 45 client.on('error', (err) => { 46 if (err.code !== 'ECONNRESET') 47 throw err; 48 }); 49 client.on('close', common.mustCall()); 50 51 const req = client.request({ ':method': 'POST' }); 52 // The client may have an ECONNRESET error here depending on the operating 53 // system, due mainly to differences in the timing of socket closing. Do 54 // not wrap this in a common mustCall. 55 req.on('error', (err) => { 56 if (err.code !== 'ECONNRESET') 57 throw err; 58 }); 59 60 req.on('aborted', common.mustCall()); 61 req.resume(); 62 63 try { 64 await once(req, 'end'); 65 } catch { 66 // Continue regardless of error. 67 } 68})); 69