Browse Source

Preserve custom properties on the original stream (#8)

Fixes #6
master
Sindre Sorhus 8 years ago
committed by GitHub
parent
commit
79ee252595
  1. 44
      index.js
  2. 22
      test/test.js

44
index.js

@ -2,6 +2,38 @@
const PassThrough = require('stream').PassThrough; const PassThrough = require('stream').PassThrough;
const zlib = require('zlib'); const zlib = require('zlib');
// We define these manually to ensure they're always copied
// even if they would move up the prototype chain
// https://nodejs.org/api/http.html#http_class_http_incomingmessage
const knownProps = [
'destroy',
'setTimeout',
'socket',
'headers',
'trailers',
'rawHeaders',
'statusCode',
'httpVersion',
'httpVersionMinor',
'httpVersionMajor',
'rawTrailers',
'statusMessage'
];
const copyProps = (fromStream, toStream) => {
const toProps = Object.keys(toStream);
const fromProps = new Set(Object.keys(fromStream).concat(knownProps));
for (const prop of fromProps) {
// Don't overwrite existing properties
if (toProps.indexOf(prop) !== -1) {
continue;
}
toStream[prop] = typeof prop === 'function' ? fromStream[prop].bind(fromStream) : fromStream[prop];
}
};
module.exports = res => { module.exports = res => {
// TODO: Use Array#includes when targeting Node.js 6 // TODO: Use Array#includes when targeting Node.js 6
if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) === -1) { if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) === -1) {
@ -11,17 +43,7 @@ module.exports = res => {
const unzip = zlib.createUnzip(); const unzip = zlib.createUnzip();
const stream = new PassThrough(); const stream = new PassThrough();
// https://nodejs.org/api/http.html#http_class_http_incomingmessage copyProps(res, stream);
stream.destroy = res.destroy.bind(res);
stream.setTimeout = res.setTimeout.bind(res);
stream.socket = res.socket;
stream.headers = res.headers;
stream.trailers = res.trailers;
stream.rawHeaders = res.rawHeaders;
stream.statusCode = res.statusCode;
stream.httpVersion = res.httpVersion;
stream.rawTrailers = res.rawTrailers;
stream.statusMessage = res.statusMessage;
unzip.on('error', err => { unzip.on('error', err => {
if (err.code === 'Z_BUF_ERROR') { if (err.code === 'Z_BUF_ERROR') {

22
test/test.js

@ -47,8 +47,18 @@ test.after('cleanup', async () => {
test('decompress gzipped content', async t => { test('decompress gzipped content', async t => {
const res = m(await httpGetP(s.url)); const res = m(await httpGetP(s.url));
t.is(typeof res.httpVersion, 'string'); t.truthy(res.destroy);
t.truthy(res.setTimeout);
t.truthy(res.socket);
t.truthy(res.headers); t.truthy(res.headers);
t.truthy(res.trailers);
t.truthy(res.rawHeaders);
t.truthy(res.statusCode);
t.truthy(res.httpVersion);
t.truthy(res.httpVersionMinor);
t.truthy(res.httpVersionMajor);
t.truthy(res.rawTrailers);
t.truthy(res.statusMessage);
res.setEncoding('utf8'); res.setEncoding('utf8');
@ -76,3 +86,13 @@ test('ignore missing data', async t => {
t.is(await getStream(res), fixture); t.is(await getStream(res), fixture);
}); });
test('preserves custom properties on the stream', async t => {
let res = await httpGetP(s.url);
res.customProp = '🦄';
res = m(res);
t.is(res.customProp, '🦄');
res.destroy();
});

Loading…
Cancel
Save