Skip to content

Commit 0e71bf4

Browse files
kanongildevinivy
andauthored
Rely on stream.destroy() whenever available (hapijs#4095)
Co-authored-by: devin ivy <devin@bigroomstudios.com>
1 parent 035f7f1 commit 0e71bf4

File tree

5 files changed

+188
-77
lines changed

5 files changed

+188
-77
lines changed

lib/response.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,14 +661,18 @@ exports = module.exports = internals.Response = class {
661661

662662
static drain(stream) {
663663

664+
if (stream.destroy) {
665+
stream.destroy();
666+
return;
667+
}
668+
669+
// Fallback for old-style streams
670+
664671
stream.unpipe();
665672

666673
if (stream.close) {
667674
stream.close();
668675
}
669-
else {
670-
stream.destroy();
671-
}
672676
}
673677
};
674678

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
"@hapi/vision": "^6.0.1",
4646
"@hapi/wreck": "^17.0.0",
4747
"handlebars": "^4.7.4",
48-
"joi": "^17.0.0"
48+
"joi": "^17.0.0",
49+
"legacy-readable-stream": "npm:readable-stream@^1.0.34"
4950
},
5051
"scripts": {
5152
"test": "lab -a @hapi/code -t 100 -L -m 5000",

test/request.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ describe('Request', () => {
984984
expect(called).to.be.false();
985985
});
986986

987-
it('closes response after server timeout', async () => {
987+
it('destroys response after server timeout', async () => {
988988

989989
const team = new Teamwork.Team();
990990
const handler = async (request) => {
@@ -998,7 +998,7 @@ describe('Request', () => {
998998
this.push(null);
999999
};
10001000

1001-
stream.close = () => team.attend();
1001+
stream._destroy = () => team.attend();
10021002
return stream;
10031003
};
10041004

test/response.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const Stream = require('stream');
88
const Code = require('@hapi/code');
99
const Handlebars = require('handlebars');
1010
const Hapi = require('..');
11-
const Hoek = require('@hapi/hoek');
1211
const Inert = require('@hapi/inert');
1312
const Lab = require('@hapi/lab');
1413
const Vision = require('@hapi/vision');
@@ -1188,45 +1187,43 @@ describe('Response', () => {
11881187
server.route({ method: 'GET', path: '/stream', handler: streamHandler });
11891188
server.route({ method: 'GET', path: '/writable', handler: writableHandler });
11901189

1191-
let updates = 0;
1192-
server.events.on({ name: 'request', channels: 'error' }, (request, event) => {
1193-
1194-
expect(event.error).to.be.an.error('Stream must have a readable interface');
1195-
++updates;
1196-
});
1197-
11981190
await server.initialize();
11991191

1192+
const log1 = server.events.once({ name: 'request', channels: 'error' });
12001193
const res1 = await server.inject('/stream');
12011194
expect(res1.statusCode).to.equal(500);
12021195

1196+
const [, event1] = await log1;
1197+
expect(event1.error).to.be.an.error('Stream must have a readable interface');
1198+
1199+
const log2 = server.events.once({ name: 'request', channels: 'error' });
12031200
const res2 = await server.inject('/writable');
12041201
expect(res2.statusCode).to.equal(500);
12051202

1206-
await Hoek.wait(10);
1207-
1208-
expect(updates).to.equal(2);
1203+
const [, event2] = await log2;
1204+
expect(event2.error).to.be.an.error('Stream must have a readable interface');
12091205
});
12101206

12111207
it('errors on an http client stream response', async () => {
12121208

1213-
const handler = (request, h) => {
1214-
1215-
return h.response('just a string');
1216-
};
1217-
12181209
const streamHandler = (request, h) => {
12191210

1220-
return h.response(Http.get(request.server.info + '/'));
1211+
const req = Http.get(request.server.info.uri);
1212+
req.abort();
1213+
return h.response(req);
12211214
};
12221215

12231216
const server = Hapi.server({ debug: false });
1224-
server.route({ method: 'GET', path: '/', handler });
12251217
server.route({ method: 'GET', path: '/stream', handler: streamHandler });
12261218

1219+
const log = server.events.once({ name: 'request', channels: 'error' });
1220+
12271221
await server.initialize();
12281222
const res = await server.inject('/stream');
12291223
expect(res.statusCode).to.equal(500);
1224+
1225+
const [, event] = await log;
1226+
expect(event.error).to.be.an.error('Stream must have a readable interface');
12301227
});
12311228

12321229
it('errors on objectMode stream response', async () => {
@@ -1260,8 +1257,13 @@ describe('Response', () => {
12601257
const server = Hapi.server({ debug: false });
12611258
server.route({ method: 'GET', path: '/', handler });
12621259

1260+
const log = server.events.once({ name: 'request', channels: 'error' });
1261+
12631262
const res = await server.inject('/');
12641263
expect(res.statusCode).to.equal(500);
1264+
1265+
const [, event] = await log;
1266+
expect(event.error).to.be.an.error('Cannot reply with stream in object mode');
12651267
});
12661268
});
12671269

0 commit comments

Comments
 (0)