• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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