Add error event hander for the body stream even if the body isn't accessed (#379)

Fixes #378
This commit is contained in:
Moritz 2018-01-27 20:20:05 +01:00 committed by Timothy Gu
parent a9c76c19ac
commit 19b115f9dc
2 changed files with 46 additions and 0 deletions

View File

@ -12,6 +12,7 @@ const Stream = require('stream');
const { PassThrough } = require('stream');
const DISTURBED = Symbol('disturbed');
const ERROR = Symbol('error');
let convert;
try { convert = require('encoding').convert; } catch(e) {}
@ -49,8 +50,15 @@ export default function Body(body, {
}
this.body = body;
this[DISTURBED] = false;
this[ERROR] = null;
this.size = size;
this.timeout = timeout;
if (this.body instanceof Stream) {
this.body.on('error', err => {
this[ERROR] = new FetchError(`Invalid response body while trying to fetch ${this.url}: ${err.message}`, 'system', err);
});
}
}
Body.prototype = {
@ -153,6 +161,10 @@ function consumeBody(body) {
this[DISTURBED] = true;
if (this[ERROR]) {
return Body.Promise.reject(this[ERROR]);
}
// body is null
if (this.body === null) {
return Body.Promise.resolve(Buffer.alloc(0));

View File

@ -587,6 +587,40 @@ describe('node-fetch', () => {
});
});
it('should handle errors on the body stream even if it is not used', function(done) {
url = `${base}invalid-content-encoding`;
fetch(url)
.then(res => {
expect(res.status).to.equal(200);
})
.catch(() => {})
.then(() => {
// Wait a few ms to see if a uncaught error occurs
setTimeout(() => {
done();
}, 50);
});
});
it('should collect handled errors on the body stream to reject if the body is used later', function() {
function delay(value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(value)
}, 100);
});
}
url = `${base}invalid-content-encoding`;
return fetch(url).then(delay).then(res => {
expect(res.headers.get('content-type')).to.equal('text/plain');
return expect(res.text()).to.eventually.be.rejected
.and.be.an.instanceOf(FetchError)
.and.have.property('code', 'Z_DATA_ERROR');
});
});
it('should allow disabling auto decompression', function() {
url = `${base}gzip`;
opts = {