1// Flags: --expose-gc 2'use strict'; 3const common = require('../common'); 4if (!common.hasCrypto) 5 common.skip('missing crypto'); 6const assert = require('assert'); 7const http2 = require('http2'); 8const makeDuplexPair = require('../common/duplexpair'); 9 10// Make sure the Http2Stream destructor works, since we don't clean the 11// stream up like we would otherwise do. 12process.on('exit', global.gc); 13 14{ 15 const { clientSide, serverSide } = makeDuplexPair(); 16 17 let serverSideHttp2Stream; 18 let serverSideHttp2StreamDestroyed = false; 19 const server = http2.createServer(); 20 server.on('stream', common.mustCall((stream, headers) => { 21 serverSideHttp2Stream = stream; 22 stream.respond({ 23 'content-type': 'text/html', 24 ':status': 200 25 }); 26 27 const originalWrite = serverSide._write; 28 serverSide._write = (buf, enc, cb) => { 29 if (serverSideHttp2StreamDestroyed) { 30 serverSide.destroy(); 31 serverSide.write = () => {}; 32 } else { 33 setImmediate(() => { 34 originalWrite.call(serverSide, buf, enc, () => setImmediate(cb)); 35 }); 36 } 37 }; 38 39 // Enough data to fit into a single *session* window, 40 // not enough data to fit into a single *stream* window. 41 stream.write(Buffer.alloc(40000)); 42 })); 43 44 server.emit('connection', serverSide); 45 46 const client = http2.connect('http://localhost:80', { 47 createConnection: common.mustCall(() => clientSide) 48 }); 49 50 const req = client.request({ ':path': '/' }); 51 52 req.on('response', common.mustCall((headers) => { 53 assert.strictEqual(headers[':status'], 200); 54 })); 55 56 req.on('data', common.mustCallAtLeast(() => { 57 if (!serverSideHttp2StreamDestroyed) { 58 serverSideHttp2Stream.destroy(); 59 serverSideHttp2StreamDestroyed = true; 60 } 61 })); 62} 63