1'use strict'; 2 3const common = require('../common'); 4if (!common.hasCrypto) 5 common.skip('missing crypto'); 6const assert = require('assert'); 7const http2 = require('http2'); 8 9const server = http2.createServer(); 10server.on('stream', common.mustCall((stream, headers) => { 11 const port = server.address().port; 12 if (headers[':path'] === '/') { 13 stream.pushStream({ 14 ':scheme': 'http', 15 ':path': '/foobar', 16 ':authority': `localhost:${port}`, 17 }, common.mustCall((err, push, headers) => { 18 assert.ifError(err); 19 push.respond({ 20 'content-type': 'text/html', 21 ':status': 200, 22 'x-push-data': 'pushed by server', 23 }); 24 push.end('pushed by server data'); 25 26 assert.throws(() => { 27 push.pushStream({}, common.mustNotCall()); 28 }, { 29 code: 'ERR_HTTP2_NESTED_PUSH', 30 name: 'Error' 31 }); 32 33 stream.end('test'); 34 })); 35 } 36 stream.respond({ 37 'content-type': 'text/html', 38 ':status': 200 39 }); 40})); 41 42server.listen(0, common.mustCall(() => { 43 const port = server.address().port; 44 const headers = { ':path': '/' }; 45 const client = http2.connect(`http://localhost:${port}`); 46 const req = client.request(headers); 47 48 client.on('stream', common.mustCall((stream, headers) => { 49 assert.strictEqual(headers[':scheme'], 'http'); 50 assert.strictEqual(headers[':path'], '/foobar'); 51 assert.strictEqual(headers[':authority'], `localhost:${port}`); 52 stream.on('push', common.mustCall((headers) => { 53 assert.strictEqual(headers[':status'], 200); 54 assert.strictEqual(headers['content-type'], 'text/html'); 55 assert.strictEqual(headers['x-push-data'], 'pushed by server'); 56 })); 57 stream.on('aborted', common.mustNotCall()); 58 // We have to read the data of the push stream to end gracefully. 59 stream.resume(); 60 })); 61 62 let data = ''; 63 64 req.on('data', common.mustCall((d) => data += d)); 65 req.on('end', common.mustCall(() => { 66 assert.strictEqual(data, 'test'); 67 server.close(); 68 client.close(); 69 })); 70 req.end(); 71})); 72