From 7176963ac268429f83a5cf0d6cee9699c7b1dd0a Mon Sep 17 00:00:00 2001 From: Carlos Fuentes Date: Fri, 21 Apr 2023 10:58:16 +0200 Subject: [PATCH] test: add testing for h2 --- lib/core/util.js | 13 +++++++++-- test/http2.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 test/http2.js diff --git a/lib/core/util.js b/lib/core/util.js index 31bad359fde..336c68d648c 100644 --- a/lib/core/util.js +++ b/lib/core/util.js @@ -5,7 +5,7 @@ const { kDestroyed, kBodyUsed } = require('./symbols') const { IncomingMessage } = require('http') const stream = require('stream') const net = require('net') -const { InvalidArgumentError } = require('./errors') +const { InvalidArgumentError, ClientDestroyedError } = require('./errors') const { Blob } = require('buffer') const nodeUtil = require('util') const { stringify } = require('querystring') @@ -199,7 +199,16 @@ function destroy (stream, err) { // See: https://github.com/nodejs/node/pull/38505/files stream.socket = null } - stream.destroy(err) + + // HTTP/2 - It causes to throw uncaught exceptions due to the + // error passed down the socket.destroy + if (stream.alpnProtocol === 'h2' && + Object.getPrototypeOf(err).constructor === ClientDestroyedError + ) { + stream.destroy() + } else { + stream.destroy(err) + } } else if (err) { process.nextTick((stream, err) => { stream.emit('error', err) diff --git a/test/http2.js b/test/http2.js new file mode 100644 index 00000000000..840fd6b2252 --- /dev/null +++ b/test/http2.js @@ -0,0 +1,56 @@ +'use strict' + +const { createSecureServer } = require('node:http2') +const { once } = require('node:events') + +const { test } = require('tap') +const pem = require('https-pem') + +const { Client } = require('..') + +test('Should support H2 connection', async t => { + const body = [] + const server = createSecureServer(pem) + + server.on('stream', (stream, headers) => { + t.equal(headers['x-my-header'], 'foo') + t.equal(headers[':method'], 'GET') + stream.respond({ + 'content-type': 'text/plain; charset=utf-8', + 'x-custom-h2': 'hello', + ':status': 200 + }) + stream.end('hello h2!') + }) + + server.listen(0) + await once(server, 'listening') + + const client = new Client(`https://localhost:${server.address().port}`, { + connect: { + rejectUnauthorized: false + } + }) + + t.plan(6) + t.teardown(server.close.bind(server)) + t.teardown(client.close.bind(client)) + + const response = await client.request({ + path: '/', + method: 'GET', + headers: { + 'x-my-header': 'foo' + } + }) + + response.body.on('data', chunk => { + body.push(chunk) + }) + + await once(response.body, 'end') + t.equal(response.statusCode, 200) + t.equal(response.headers['content-type'], 'text/plain; charset=utf-8') + t.equal(response.headers['x-custom-h2'], 'hello') + t.equal(Buffer.concat(body).toString('utf8'), 'hello h2!') +})