Skip to content

Commit c49b9c8

Browse files
committed
Expose compressor to response streams. Closes #3599
1 parent 5031700 commit c49b9c8

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

API.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3323,7 +3323,13 @@ The return value must be one of:
33233323
- `Stream` object
33243324
- must be compatible with the "streams2" API and not be in `objectMode`.
33253325
- if the stream object has a `statusCode` property, that status code will be used as
3326-
the default response code.
3326+
the default response code based on the [`passThrough`](#response.settings.passThrough)
3327+
option.
3328+
- if the stream object has a `headers` property, the headers will be included in the response
3329+
based on the [`passThrough`](#response.settings.passThrough) option.
3330+
- if the stream object has a function property `setCompressor(compressor)` and the response
3331+
passes through a compressor, a reference to the compressor stream will be passed to the
3332+
response stream via this method.
33273333
- any object or array
33283334
- must not include circular references.
33293335
- a toolkit signal:

lib/transmit.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,14 @@ internals.encoding = function (response, encoding) {
222222

223223
delete response.headers['content-length'];
224224
response._header('content-encoding', encoding);
225-
return request._core.compression.encoder(request, encoding);
225+
const compressor = request._core.compression.encoder(request, encoding);
226+
if (response.variety === 'stream' &&
227+
typeof response._payload.setCompressor === 'function') {
228+
229+
response._payload.setCompressor(compressor);
230+
}
231+
232+
return compressor;
226233
};
227234

228235

test/transmit.js

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,8 @@ describe('transmission', () => {
371371
expect(res.headers['content-encoding']).to.equal('gzip');
372372
expect(res.headers.vary).to.equal('accept-encoding');
373373

374-
await new Promise((resolve) => {
375-
376-
Zlib.unzip(res.rawPayload, (err, result) => {
377-
378-
expect(err).to.not.exist();
379-
expect(result.toString()).to.equal('/**/docall({"first":"1","last":"2"});');
380-
resolve();
381-
});
382-
});
374+
const uncompressed = await internals.uncompress('unzip', res.rawPayload);
375+
expect(uncompressed.toString()).to.equal('/**/docall({"first":"1","last":"2"});');
383376
});
384377

385378
it('returns an JSONP response when response is a buffer', async () => {
@@ -1772,6 +1765,49 @@ describe('transmission', () => {
17721765
});
17731766
});
17741767

1768+
describe('encoding()', () => {
1769+
1770+
it('passes compressor to stream', async () => {
1771+
1772+
const handler = (request, h) => {
1773+
1774+
const TestStream = class extends Stream.Readable {
1775+
1776+
_read(size) {
1777+
1778+
if (this.isDone) {
1779+
return;
1780+
}
1781+
this.isDone = true;
1782+
1783+
this.push('some payload');
1784+
this._compressor.flush();
1785+
1786+
setTimeout(() => {
1787+
1788+
this.push(' and some other payload');
1789+
this.push(null);
1790+
}, 10);
1791+
}
1792+
1793+
setCompressor(compressor) {
1794+
1795+
this._compressor = compressor;
1796+
}
1797+
};
1798+
1799+
return h.response(new TestStream()).type('text/html');
1800+
};
1801+
1802+
const server = Hapi.server({ compression: { minBytes: 1 } });
1803+
server.route({ method: 'GET', path: '/', handler });
1804+
1805+
const res = await server.inject({ url: '/', headers: { 'accept-encoding': 'gzip' } });
1806+
const uncompressed = await internals.uncompress('unzip', res.rawPayload);
1807+
expect(uncompressed.toString()).to.equal('some payload and some other payload');
1808+
});
1809+
});
1810+
17751811
describe('writeHead()', () => {
17761812

17771813
it('set custom statusMessage', async () => {
@@ -1841,3 +1877,9 @@ internals.compress = function (encoder, value) {
18411877

18421878
return new Promise((resolve) => Zlib[encoder](value, (ignoreErr, compressed) => resolve(compressed)));
18431879
};
1880+
1881+
1882+
internals.uncompress = function (decoder, value) {
1883+
1884+
return new Promise((resolve) => Zlib[decoder](value, (ignoreErr, uncompressed) => resolve(uncompressed)));
1885+
};

0 commit comments

Comments
 (0)