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.mustSucceed((push, headers) => { 18 push.respond({ 19 'content-type': 'text/html', 20 ':status': 200, 21 'x-push-data': 'pushed by server', 22 }); 23 push.end('pushed by server data'); 24 25 assert.throws(() => { 26 push.pushStream({}, common.mustNotCall()); 27 }, { 28 code: 'ERR_HTTP2_NESTED_PUSH', 29 name: 'Error' 30 }); 31 32 stream.end('test'); 33 })); 34 } 35 stream.respond({ 36 'content-type': 'text/html', 37 ':status': 200 38 }); 39})); 40 41server.listen(0, common.mustCall(() => { 42 const port = server.address().port; 43 const headers = { ':path': '/' }; 44 const client = http2.connect(`http://localhost:${port}`); 45 const req = client.request(headers); 46 47 client.on('stream', common.mustCall((stream, headers) => { 48 assert.strictEqual(headers[':scheme'], 'http'); 49 assert.strictEqual(headers[':path'], '/foobar'); 50 assert.strictEqual(headers[':authority'], `localhost:${port}`); 51 stream.on('push', common.mustCall((headers) => { 52 assert.strictEqual(headers[':status'], 200); 53 assert.strictEqual(headers['content-type'], 'text/html'); 54 assert.strictEqual(headers['x-push-data'], 'pushed by server'); 55 })); 56 stream.on('aborted', common.mustNotCall()); 57 // We have to read the data of the push stream to end gracefully. 58 stream.resume(); 59 })); 60 61 let data = ''; 62 63 req.on('data', common.mustCall((d) => data += d)); 64 req.on('end', common.mustCall(() => { 65 assert.strictEqual(data, 'test'); 66 server.close(); 67 client.close(); 68 })); 69 req.end(); 70})); 71