1'use strict'; 2// Flags: --expose-internals 3 4const common = require('../common'); 5 6if (!common.hasCrypto) 7 common.skip('missing crypto'); 8 9const fixtures = require('../common/fixtures'); 10 11const http2 = require('http2'); 12 13const { internalBinding } = require('internal/test/binding'); 14const { 15 constants, 16 Http2Stream, 17 nghttp2ErrorString 18} = internalBinding('http2'); 19const { NghttpError } = require('internal/http2/util'); 20 21// Tests error handling within processRespondWithFD 22// (called by respondWithFD & respondWithFile) 23// - every other NGHTTP2 error from binding (should emit stream error) 24 25const fname = fixtures.path('elipses.txt'); 26 27const specificTestKeys = []; 28const specificTests = []; 29 30const genericTests = Object.getOwnPropertyNames(constants) 31 .filter((key) => ( 32 key.indexOf('NGHTTP2_ERR') === 0 && specificTestKeys.indexOf(key) < 0 33 )) 34 .map((key) => ({ 35 ngError: constants[key], 36 error: { 37 code: 'ERR_HTTP2_ERROR', 38 constructor: NghttpError, 39 name: 'Error', 40 message: nghttp2ErrorString(constants[key]) 41 }, 42 type: 'stream' 43 })); 44 45 46const tests = specificTests.concat(genericTests); 47 48let currentError; 49 50// Mock `respond` because we only care about testing error handling 51Http2Stream.prototype.respond = () => currentError.ngError; 52 53const server = http2.createServer(); 54server.on('stream', common.mustCall((stream, headers) => { 55 const errorMustCall = common.expectsError(currentError.error); 56 const errorMustNotCall = common.mustNotCall( 57 `${currentError.error.code} should emit on ${currentError.type}` 58 ); 59 60 if (currentError.type === 'stream') { 61 stream.session.on('error', errorMustNotCall); 62 stream.on('error', errorMustCall); 63 stream.on('error', common.mustCall(() => { 64 stream.destroy(); 65 })); 66 } else { 67 stream.session.once('error', errorMustCall); 68 stream.on('error', errorMustNotCall); 69 } 70 71 stream.respondWithFile(fname); 72}, tests.length)); 73 74server.listen(0, common.mustCall(() => runTest(tests.shift()))); 75 76function runTest(test) { 77 const port = server.address().port; 78 const url = `http://localhost:${port}`; 79 const headers = { 80 ':path': '/', 81 ':method': 'POST', 82 ':scheme': 'http', 83 ':authority': `localhost:${port}` 84 }; 85 86 const client = http2.connect(url); 87 const req = client.request(headers); 88 89 req.on('error', common.expectsError({ 90 code: 'ERR_HTTP2_STREAM_ERROR', 91 name: 'Error', 92 message: 'Stream closed with error code NGHTTP2_INTERNAL_ERROR' 93 })); 94 95 currentError = test; 96 req.resume(); 97 req.end(); 98 99 req.on('end', common.mustCall(() => { 100 client.close(); 101 102 if (!tests.length) { 103 server.close(); 104 } else { 105 runTest(tests.shift()); 106 } 107 })); 108} 109