1'use strict'; 2 3const common = require('../common'); 4if (!common.hasCrypto) 5 common.skip('missing crypto'); 6const assert = require('assert'); 7const h2 = require('http2'); 8const body = 9 '<html><head></head><body><h1>this is some data</h2></body></html>'; 10const trailerKey = 'test-trailer'; 11const trailerValue = 'testing'; 12 13const server = h2.createServer(); 14 15// We use the lower-level API here 16server.on('stream', common.mustCall(onStream)); 17 18function onStream(stream, headers, flags) { 19 stream.on('trailers', common.mustCall((headers) => { 20 assert.strictEqual(headers[trailerKey], trailerValue); 21 stream.end(body); 22 })); 23 stream.respond({ 24 'content-type': 'text/html', 25 ':status': 200 26 }, { waitForTrailers: true }); 27 stream.on('wantTrailers', () => { 28 stream.sendTrailers({ [trailerKey]: trailerValue }); 29 assert.throws( 30 () => stream.sendTrailers({}), 31 { 32 code: 'ERR_HTTP2_TRAILERS_ALREADY_SENT', 33 name: 'Error' 34 } 35 ); 36 }); 37 38 assert.throws( 39 () => stream.sendTrailers({}), 40 { 41 code: 'ERR_HTTP2_TRAILERS_NOT_READY', 42 name: 'Error' 43 } 44 ); 45} 46 47server.listen(0); 48 49server.on('listening', common.mustCall(function() { 50 const client = h2.connect(`http://localhost:${this.address().port}`); 51 const req = client.request({ ':path': '/', ':method': 'POST' }, 52 { waitForTrailers: true }); 53 req.on('wantTrailers', () => { 54 req.sendTrailers({ [trailerKey]: trailerValue }); 55 }); 56 req.on('data', common.mustCall()); 57 req.on('trailers', common.mustCall((headers) => { 58 assert.strictEqual(headers[trailerKey], trailerValue); 59 })); 60 req.on('close', common.mustCall(() => { 61 assert.throws( 62 () => req.sendTrailers({}), 63 { 64 code: 'ERR_HTTP2_INVALID_STREAM', 65 name: 'Error' 66 } 67 ); 68 server.close(); 69 client.close(); 70 })); 71 req.end('data'); 72 73})); 74