Ivan Socolsky
9 years ago
5 changed files with 270 additions and 34 deletions
@ -0,0 +1,57 @@ |
|||||
|
var _ = require('lodash'); |
||||
|
var async = require('async'); |
||||
|
var $ = require('preconditions').singleton(); |
||||
|
|
||||
|
var log = require('npmlog'); |
||||
|
log.debug = log.verbose; |
||||
|
|
||||
|
/** |
||||
|
* Query a server, using one of the given options |
||||
|
* |
||||
|
* @param {Object} opts |
||||
|
* @param {Array} opts.hosts Array of hosts to query. Until the first success one. |
||||
|
* @param {Array} opts.path Path to request in each server |
||||
|
*/ |
||||
|
var requestList = function(args, cb) { |
||||
|
$.checkArgument(args.hosts); |
||||
|
request = args.request || require('request'); |
||||
|
|
||||
|
if (!_.isArray(args.hosts)) |
||||
|
args.hosts = [args.hosts]; |
||||
|
|
||||
|
var urls = _.map(args.hosts, function(x) { |
||||
|
return (x + args.path); |
||||
|
}); |
||||
|
var nextUrl, result, success; |
||||
|
|
||||
|
async.whilst( |
||||
|
function() { |
||||
|
nextUrl = urls.shift(); |
||||
|
return nextUrl && !success; |
||||
|
}, |
||||
|
function(a_cb) { |
||||
|
args.uri = nextUrl; |
||||
|
request(args, function(err, res, body) { |
||||
|
if (err) { |
||||
|
log.warn('REQUEST FAIL: ' + nextUrl + ' ERROR: ' + err); |
||||
|
} |
||||
|
|
||||
|
if (res) { |
||||
|
success = !!res.statusCode.toString().match(/^[1234]../); |
||||
|
if (!success) { |
||||
|
log.warn('REQUEST FAIL: ' + nextUrl + ' STATUS CODE: ' + res.statusCode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
result = [err, res, body]; |
||||
|
return a_cb(); |
||||
|
}); |
||||
|
}, |
||||
|
function(err) { |
||||
|
if (err) return cb(err); |
||||
|
return cb(result[0], result[1], result[2]); |
||||
|
} |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
module.exports = requestList; |
@ -0,0 +1,170 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
var _ = require('lodash'); |
||||
|
var chai = require('chai'); |
||||
|
var sinon = require('sinon'); |
||||
|
var should = chai.should(); |
||||
|
var prequest = require('../lib/blockchainexplorers/request-list'); |
||||
|
|
||||
|
describe('request-list', function() { |
||||
|
var request; |
||||
|
|
||||
|
beforeEach(function() { |
||||
|
request = sinon.stub(); |
||||
|
}); |
||||
|
it('should support url as string', function(done) { |
||||
|
|
||||
|
request.yields(null, { |
||||
|
statusCode: 200 |
||||
|
}, 'abc'); |
||||
|
|
||||
|
prequest({ |
||||
|
hosts: 'url1', |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
body.should.be.equal('abc'); |
||||
|
res.statusCode.should.be.equal(200); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should support url as string (500 response)', function(done) { |
||||
|
request.yields(null, { |
||||
|
statusCode: 500 |
||||
|
}); |
||||
|
prequest({ |
||||
|
hosts: 'url1', |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
res.statusCode.should.be.equal(500); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should support url as array of strings', function(done) { |
||||
|
request.yields(null, { |
||||
|
statusCode: 200 |
||||
|
}, 'abc'); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
body.should.be.equal('abc'); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should try 2nd url if first is unsuccessful (5xx)', function(done) { |
||||
|
request.onCall(0).yields(null, { |
||||
|
statusCode: 500 |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 550 |
||||
|
}); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
res.statusCode.should.be.equal(550); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should query 3th url if first 2 are unsuccessful (5xx)', function(done) { |
||||
|
request.onCall(0).yields(null, { |
||||
|
statusCode: 500 |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 550 |
||||
|
}); |
||||
|
request.onCall(2).yields(null, { |
||||
|
statusCode: 200, |
||||
|
}, 'abc'); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2', 'url3'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
body.should.be.equal('abc'); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should query only the first url if response is 404', function(done) { |
||||
|
request.onCall(0).yields(null, { |
||||
|
statusCode: 404 |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 550 |
||||
|
}); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
res.statusCode.should.be.equal(404); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should query only the first 2 urls if the second is successfull (5xx)', function(done) { |
||||
|
request.onCall(0).yields(null, { |
||||
|
statusCode: 500 |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 200, |
||||
|
}, '2nd'); |
||||
|
request.onCall(2).yields(null, { |
||||
|
statusCode: 200, |
||||
|
}, 'abc'); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2', 'url3'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
body.should.be.equal('2nd'); |
||||
|
res.statusCode.should.be.equal(200); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
it('should query only the first 2 urls if the second is successfull (timeout)', function(done) { |
||||
|
request.onCall(0).yields({ |
||||
|
code: 'ETIMEDOUT', |
||||
|
connect: true |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 200, |
||||
|
}, '2nd'); |
||||
|
request.onCall(2).yields(null, { |
||||
|
statusCode: 200, |
||||
|
}, 'abc'); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2', 'url3'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
body.should.be.equal('2nd'); |
||||
|
res.statusCode.should.be.equal(200); |
||||
|
done(); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
it('should use the latest response if all requests are unsuccessfull', function(done) { |
||||
|
request.onCall(0).yields({ |
||||
|
code: 'ETIMEDOUT', |
||||
|
connect: true |
||||
|
}); |
||||
|
request.onCall(1).yields(null, { |
||||
|
statusCode: 505, |
||||
|
}, '2nd'); |
||||
|
request.onCall(2).yields(null, { |
||||
|
statusCode: 510, |
||||
|
}, 'abc'); |
||||
|
prequest({ |
||||
|
hosts: ['url1', 'url2', 'url3'], |
||||
|
request: request, |
||||
|
}, function(err, res, body) { |
||||
|
should.not.exist(err); |
||||
|
res.statusCode.should.be.equal(510); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
Loading…
Reference in new issue