add request timeout

fix GH-12
This commit is contained in:
freewil 2014-03-11 17:14:49 -07:00
parent b490f03e1c
commit 5d83f0e43a
2 changed files with 98 additions and 2 deletions

View File

@ -54,13 +54,41 @@ Client.prototype.call = function(method, params, callback, errback, path) {
if (this.opts.user && this.opts.pass) {
requestOptions.auth = this.opts.user + ':' + this.opts.pass;
}
// Now we'll make a request to the server
var cbCalled = false;
var request = this.http.request(requestOptions);
// start request timeout timer
var reqTimeout = setTimeout(function() {
if (cbCalled) return;
cbCalled = true;
request.abort();
var err = new Error('ETIMEDOUT');
err.code = 'ETIMEDOUT';
errback(err);
}, this.opts.timeout || 5000);
// set additional timeout on socket in case of remote freeze after sending headers
request.setTimeout(this.opts.timeout || 5000, function() {
if (cbCalled) return;
cbCalled = true;
request.abort();
var err = new Error('ESOCKETTIMEDOUT')
err.code = 'ESOCKETTIMEDOUT'
errback(err);
});
request.on('error', errback);
request.on('error', function(err) {
if (cbCalled) return;
cbCalled = true;
clearTimeout(reqTimeout);
errback(err);
});
request.on('response', function(response) {
clearTimeout(reqTimeout);
// We need to buffer the response chunks in a nonblocking way.
var buffer = '';
response.on('data', function(chunk) {
@ -72,6 +100,9 @@ Client.prototype.call = function(method, params, callback, errback, path) {
response.on('end', function() {
var err;
if (cbCalled) return;
cbCalled = true;
try {
var decoded = JSON.parse(buffer);
} catch (e) {

View File

@ -1,5 +1,6 @@
var assert = require('assert'),
clone = require('clone'),
http = require('http'),
bitcoin = require('../'),
config = require('./config');
@ -16,6 +17,12 @@ var notEmpty = function notEmpty(data) {
assert.ok(data);
};
var makeServer = function(port) {
var server = http.createServer();
server.listen(port);
return server;
};
describe('Client', function() {
describe('getAccountAddress()', function() {
@ -209,4 +216,62 @@ describe('Client', function() {
});
});
describe('request timeouts', function() {
it('should occur by default after 5000ms', function(done) {
this.timeout(7500);
var server = makeServer(19998);
var request;
var response;
server.on('request', function(req, res) {
request = req;
response = res;
});
var client = new bitcoin.Client({
host: 'localhost',
port: 19998,
user: 'admin1',
pass: '123'
});
var start = Date.now();
client.getInfo(function(err, info) {
var delta = Date.now() - start;
assert.ok(err instanceof Error);
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
assert.ok(delta >= 5000, 'delta should be >= 5000: ' + delta);
response.end();
server.close();
done();
});
});
it('should be customizable', function(done) {
this.timeout(4500);
var server = makeServer(19999);
var request;
var response;
server.on('request', function(req, res) {
request = req;
response = res;
});
var client = new bitcoin.Client({
host: 'localhost',
port: 19999,
user: 'admin1',
pass: '123',
timeout: 2500
});
var start = Date.now();
client.getInfo(function(err, info) {
var delta = Date.now() - start;
assert.ok(err instanceof Error);
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
assert.ok(delta >= 2500, 'delta should be >= 2500:' + delta);
response.end();
server.close();
done();
});
});
});
});