timeout on body and clear timeout internally

This commit is contained in:
David Frank 2015-04-17 13:26:55 +08:00
parent 803ed8a502
commit e09dfae0a5
4 changed files with 59 additions and 8 deletions

View File

@ -159,6 +159,7 @@ function Fetch(url, opts) {
, status: res.statusCode
, headers: headers
, size: options.size
, timeout: options.timeout
});
resolve(output);

View File

@ -27,6 +27,7 @@ function Response(body, opts) {
this.bodyUsed = false;
this.size = opts.size;
this.ok = this.status >= 200 && this.status < 300;
this.timeout = opts.timeout;
}
@ -73,6 +74,16 @@ Response.prototype._decode = function() {
this._raw = [];
return new Response.Promise(function(resolve, reject) {
var resTimeout;
// allow timeout on slow response body
if (self.timeout) {
resTimeout = setTimeout(function() {
self._abort = true;
reject(new Error('response timeout at ' + self.url + ' over limit: ' + self.timeout));
}, self.timeout);
}
self.body.on('data', function(chunk) {
if (self._abort || chunk === null) {
return;
@ -93,6 +104,7 @@ Response.prototype._decode = function() {
return;
}
clearTimeout(resTimeout);
resolve(self._convert());
});
});

View File

@ -87,6 +87,15 @@ TestServer.prototype.router = function(req, res) {
}, 1000);
}
if (p === '/slow') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.write('test');
setTimeout(function() {
res.end('test');
}, 1000);
}
if (p === '/cookie') {
res.statusCode = 200;
res.setHeader('Set-Cookie', ['a=1', 'b=1']);

View File

@ -316,6 +316,7 @@ describe('node-fetch', function() {
});
it('should allow custom timeout', function() {
this.timeout(500);
url = base + '/timeout';
opts = {
timeout: 100
@ -323,6 +324,42 @@ describe('node-fetch', function() {
return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
});
it('should allow custom timeout on response body', function() {
this.timeout(500);
url = base + '/slow';
opts = {
timeout: 100
};
return fetch(url, opts).then(function(res) {
expect(res.ok).to.be.true;
return expect(res.text()).to.eventually.be.rejectedWith(Error);
});
});
it('should clear internal timeout on fetch response', function (done) {
this.timeout(1000);
spawn('node', ['-e', 'require("./")("' + base + '/hello", { timeout: 5000 })'])
.on('exit', function () {
done();
});
});
it('should clear internal timeout on fetch redirect', function (done) {
this.timeout(1000);
spawn('node', ['-e', 'require("./")("' + base + '/redirect/301", { timeout: 5000 })'])
.on('exit', function () {
done();
});
});
it('should clear internal timeout on fetch error', function (done) {
this.timeout(1000);
spawn('node', ['-e', 'require("./")("' + base + '/error/reset", { timeout: 5000 })'])
.on('exit', function () {
done();
});
});
it('should allow POST request', function() {
url = base + '/inspect';
opts = {
@ -583,12 +620,4 @@ describe('node-fetch', function() {
expect(res.ok).to.be.true;
});
});
it('should remove timeout on response', function (done) {
this.timeout(1e3);
spawn('node', ['-e', 'require("./")("' + base + '/hello", {timeout: 1e4})'])
.on('exit', function () {
done();
});
});
});