Skip to content

Commit 0d32840

Browse files
authored
Fix req end during response transmission (hapijs#4264)
* Write test that fails on node v16 for req ending during response transmission * Fix request close during response transmission for node v16
1 parent be3e3a2 commit 0d32840

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

lib/transmit.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ internals.pipe = function (request, stream) {
257257
const end = internals.end.bind(null, env, null);
258258

259259
request.raw.req.on('aborted', aborted);
260-
request.raw.req.on('close', close);
261260

262261
request.raw.res.on('close', close);
263262
request.raw.res.on('error', end);

test/transmit.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ const Net = require('net');
77
const Path = require('path');
88
const Stream = require('stream');
99
const Zlib = require('zlib');
10+
const Events = require('events');
1011

1112
const Boom = require('@hapi/boom');
1213
const Code = require('@hapi/code');
1314
const Hapi = require('..');
1415
const Hoek = require('@hapi/hoek');
16+
const Bounce = require('@hapi/bounce');
1517
const Inert = require('@hapi/inert');
1618
const Lab = require('@hapi/lab');
1719
const LegacyReadableStream = require('legacy-readable-stream');
@@ -1921,6 +1923,63 @@ describe('transmission', () => {
19211923
const res = await server.inject('/');
19221924
expect(res.statusCode).to.equal(500);
19231925
});
1926+
1927+
it('permits ending reading request stream while transmitting response.', async (flags) => {
1928+
1929+
const server = Hapi.server();
1930+
1931+
server.route({
1932+
method: 'post',
1933+
path: '/',
1934+
options: {
1935+
payload: {
1936+
output: 'stream'
1937+
}
1938+
},
1939+
handler: (request, h) => {
1940+
1941+
const stream = new Stream.PassThrough();
1942+
1943+
// Start transmitting stream response...
1944+
stream.push('hello ');
1945+
1946+
Bounce.background(async () => {
1947+
1948+
await Events.once(request.raw.res, 'pipe');
1949+
1950+
// ...but also only read and end the request once the response is transmitting...
1951+
request.raw.req.on('data', Hoek.ignore);
1952+
await Events.once(request.raw.req, 'end');
1953+
1954+
// ...and finally end the intended response once the request stream has ended.
1955+
stream.end('world');
1956+
});
1957+
1958+
return h.response(stream);
1959+
}
1960+
});
1961+
1962+
flags.onCleanup = () => server.stop();
1963+
await server.start();
1964+
1965+
const req = Http.request({
1966+
hostname: 'localhost',
1967+
port: server.info.port,
1968+
method: 'post'
1969+
});
1970+
1971+
req.end('{}');
1972+
1973+
const [res] = await Events.once(req, 'response');
1974+
1975+
let result = '';
1976+
for await (const chunk of res) {
1977+
result += chunk.toString();
1978+
}
1979+
1980+
// If not permitted then result will be "hello " without "world"
1981+
expect(result).to.equal('hello world');
1982+
});
19241983
});
19251984

19261985
describe('length()', () => {

0 commit comments

Comments
 (0)