From 2209daa8bac707e7c68fa9239b956e56f2e25c04 Mon Sep 17 00:00:00 2001 From: Devin Ivy Date: Wed, 23 Jun 2021 00:20:18 -0400 Subject: [PATCH 1/2] Write test that fails on node v16 for req ending during response transmission --- test/transmit.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/transmit.js b/test/transmit.js index 2bc3786ff..d7af8065f 100755 --- a/test/transmit.js +++ b/test/transmit.js @@ -7,11 +7,13 @@ const Net = require('net'); const Path = require('path'); const Stream = require('stream'); const Zlib = require('zlib'); +const Events = require('events'); const Boom = require('@hapi/boom'); const Code = require('@hapi/code'); const Hapi = require('..'); const Hoek = require('@hapi/hoek'); +const Bounce = require('@hapi/bounce'); const Inert = require('@hapi/inert'); const Lab = require('@hapi/lab'); const LegacyReadableStream = require('legacy-readable-stream'); @@ -1921,6 +1923,63 @@ describe('transmission', () => { const res = await server.inject('/'); expect(res.statusCode).to.equal(500); }); + + it('permits ending reading request stream while transmitting response.', async (flags) => { + + const server = Hapi.server(); + + server.route({ + method: 'post', + path: '/', + options: { + payload: { + output: 'stream' + } + }, + handler: (request, h) => { + + const stream = new Stream.PassThrough(); + + // Start transmitting stream response... + stream.push('hello '); + + Bounce.background(async () => { + + await Events.once(request.raw.res, 'pipe'); + + // ...but also only read and end the request once the response is transmitting... + request.raw.req.on('data', Hoek.ignore); + await Events.once(request.raw.req, 'end'); + + // ...and finally end the intended response once the request stream has ended. + stream.end('world'); + }); + + return h.response(stream); + } + }); + + flags.onCleanup = () => server.stop(); + await server.start(); + + const req = Http.request({ + hostname: 'localhost', + port: server.info.port, + method: 'post' + }); + + req.end('{}'); + + const [res] = await Events.once(req, 'response'); + + let result = ''; + for await (const chunk of res) { + result += chunk.toString(); + } + + // If not permitted then result will be "hello " without "world" + expect(result).to.equal('hello world'); + }); }); describe('length()', () => { From 92af029b22e7036cd653e27b3d696920a0bc530a Mon Sep 17 00:00:00 2001 From: Devin Ivy Date: Wed, 23 Jun 2021 00:21:30 -0400 Subject: [PATCH 2/2] Fix request close during response transmission for node v16 --- lib/transmit.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/transmit.js b/lib/transmit.js index 0005eedcb..0c173e336 100755 --- a/lib/transmit.js +++ b/lib/transmit.js @@ -257,7 +257,6 @@ internals.pipe = function (request, stream) { const end = internals.end.bind(null, env, null); request.raw.req.on('aborted', aborted); - request.raw.req.on('close', close); request.raw.res.on('close', close); request.raw.res.on('error', end);