Skip to content

Commit

Permalink
Merge d8529c8 into 3a70aed
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Durst committed Jun 4, 2018
2 parents 3a70aed + d8529c8 commit 8ff7e75
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/call_builder.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {NotFoundError, NetworkError, BadRequestError} from "./errors";
import forEach from 'lodash/forEach';
import { Config } from "./config";

let URI = require("urijs");
let URITemplate = require("urijs/src/URITemplate");
Expand All @@ -17,6 +18,7 @@ let toBluebird = require("bluebird").resolve;
*/
export class CallBuilder {
constructor(serverUrl) {

this.url = serverUrl;
this.filter = [];
this.originalSegments = this.url.segment() || [];
Expand Down
23 changes: 22 additions & 1 deletion src/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import clone from 'lodash/clone';

let defaultConfig = {
allowHttp: false
allowHttp: false,
timeout: 0
};

let config = clone(defaultConfig);
Expand All @@ -13,11 +14,13 @@ let config = clone(defaultConfig);
* ```
* import {Config} from 'stellar-sdk';
* Config.setAllowHttp(true);
* Config.setTimout(5000);
* ```
*
* Usage browser:
* ```
* StellarSdk.Config.setAllowHttp(true);
* StellarSdk.Config.setTimout(5000);
* ```
* @static
*/
Expand All @@ -32,6 +35,16 @@ class Config {
config.allowHttp = value;
}

/**
* Sets `timeout` flag globally. When set to anything besides 0, the request will timeout after specified time (ms).
* Default: 0.
* @param {number} value
* @static
*/
static setTimeout(value) {
config.timeout = value;
}

/**
* Returns the value of `allowHttp` flag.
* @static
Expand All @@ -40,6 +53,14 @@ class Config {
return clone(config.allowHttp);
}

/**
* Returns the value of `timeout` flag.
* @static
*/
static getTimeout() {
return clone(config.timeout);
}

/**
* Sets all global config flags to default values.
* @static
Expand Down
8 changes: 6 additions & 2 deletions src/federation_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class FederationServer {
* @param {string} value Stellar Address (ex. `bob*stellar.org`)
* @param {object} [opts]
* @param {boolean} [opts.allowHttp] - Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
* @param {number} [opts.timeout] - Allow a timeout, default: 0. Allows user to avoid nasty lag due to TOML resolve issue.
* @returns {Promise}
*/
static resolve(value, opts = {}) {
Expand Down Expand Up @@ -109,10 +110,11 @@ export class FederationServer {
* @param {string} domain Domain to get federation server for
* @param {object} [opts]
* @param {boolean} [opts.allowHttp] - Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
* @param {number} [opts.timeout] - Allow a timeout, default: 0. Allows user to avoid nasty lag due to TOML resolve issue.
* @returns {Promise}
*/
static createForDomain(domain, opts = {}) {
return StellarTomlResolver.resolve(domain)
return StellarTomlResolver.resolve(domain, opts)
.then(tomlObject => {
if (!tomlObject.FEDERATION_SERVER) {
return Promise.reject(new Error('stellar.toml does not contain FEDERATION_SERVER field'));
Expand Down Expand Up @@ -161,7 +163,9 @@ export class FederationServer {
}

_sendRequest(url) {
return axios.get(url.toString(), {maxContentLength: FEDERATION_RESPONSE_MAX_SIZE})
let timeout = this.timeout | Config.getTimeout();

return axios.get(url.toString(), {maxContentLength: FEDERATION_RESPONSE_MAX_SIZE, timeout})
.then(response => {
if (typeof response.data.memo != "undefined" && typeof response.data.memo != 'string') {
throw new Error("memo value should be of type string");
Expand Down
10 changes: 9 additions & 1 deletion src/stellar_toml_resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,27 @@ export class StellarTomlResolver {
* @param {string} domain Domain to get stellar.toml file for
* @param {object} [opts]
* @param {boolean} [opts.allowHttp] - Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
* @param {number} [opts.timeout] - Allow a timeout, default: 0. Allows user to avoid nasty lag due to TOML resolve issue.
* @returns {Promise}
*/
static resolve(domain, opts = {}) {
let allowHttp = Config.isAllowHttp();
let timeout = Config.getTimeout();

if (typeof opts.allowHttp !== 'undefined') {
allowHttp = opts.allowHttp;
}

if (typeof opts.timeout === 'number') {
timeout = opts.timeout;
}

let protocol = 'https';
if (allowHttp) {
protocol = 'http';
}
return axios.get(`${protocol}://${domain}/.well-known/stellar.toml`, {maxContentLength: STELLAR_TOML_MAX_SIZE})

return axios.get(`${protocol}://${domain}/.well-known/stellar.toml`, {maxContentLength: STELLAR_TOML_MAX_SIZE, timeout})
.then(response => {
try {
let tomlObject = toml.parse(response.data);
Expand Down
108 changes: 108 additions & 0 deletions test/unit/federation_server_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,5 +227,113 @@ FEDERATION_SERVER="https://api.stellar.org/federation"
.then(() => tempServer.close());
});
});

});

describe('FederationServer timeout', function () {

it("times out when resolveAddress response lags", function (done) {
StellarSdk.Config.setTimeout(100);

// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.FEDERATION_RESPONSE_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=UTF-8');
setTimeout(() => {
res.end(response);
}, 10000);
}).listen(4444, () => {
new StellarSdk.FederationServer('http://localhost:4444/federation', 'stellar.org', {allowHttp: true})
.resolveAddress('bob*stellar.org')
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});

it("times out when resolveAccountId response lags", function (done) {
StellarSdk.Config.setTimeout(100);

// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.FEDERATION_RESPONSE_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=UTF-8');
setTimeout(() => {
res.end(response);
}, 10000);
}).listen(4444, () => {
new StellarSdk.FederationServer('http://localhost:4444/federation', 'stellar.org', {allowHttp: true})
.resolveAccountId('GB5XVAABEQMY63WTHDQ5RXADGYF345VWMNPTN2GFUDZT57D57ZQTJ7PS')
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});

it("times out when resolveTransactionId response lags", function (done) {
StellarSdk.Config.setTimeout(100);

// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.FEDERATION_RESPONSE_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=UTF-8');
setTimeout(() => {
res.end(response);
}, 10000);
}).listen(4444, () => {
new StellarSdk.FederationServer('http://localhost:4444/federation', 'stellar.org', {allowHttp: true})
.resolveTransactionId('3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889')
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});

it("times out when createForDomain response lags", function (done) {
// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.STELLAR_TOML_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
setTimeout(() => {
res.setHeader('Content-Type', 'text/x-toml; charset=UTF-8');
res.end(response);
}, 1000);
}).listen(4444, () => {
StellarSdk.FederationServer.createForDomain("localhost:4444", {allowHttp: true, timeout: 100})
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});

it("times out when resolve response lags", function (done) {
// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.FEDERATION_RESPONSE_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
setTimeout(() => {
res.end(response);
}, 10000);
}).listen(4444, () => {
StellarSdk.FederationServer
.resolve('bob*localhost:4444', {allowHttp: true, timeout: 100})
.should.eventually.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});
});
});
39 changes: 39 additions & 0 deletions test/unit/stellar_toml_resolver_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,44 @@ FEDERATION_SERVER="https://api.stellar.org/federation"
.then(() => tempServer.close());
});
});

it("rejects after given timeout when global Config.timeout flag is set", function (done) {
StellarSdk.Config.setTimeout(100);

if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.STELLAR_TOML_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
setTimeout(() => {
res.setHeader('Content-Type', 'text/x-toml; charset=UTF-8');
res.end(response);
}, 10000);
}).listen(4444, () => {
StellarSdk.StellarTomlResolver.resolve("localhost:4444", {allowHttp: true})
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});

it("rejects after given timeout when timeout specified in StellarTomlResolver opts param", function (done) {
// Unable to create temp server in a browser
if (typeof window != 'undefined') {
return done();
}
var response = Array(StellarSdk.STELLAR_TOML_MAX_SIZE+10).join('a');
let tempServer = http.createServer((req, res) => {
setTimeout(() => {
res.setHeader('Content-Type', 'text/x-toml; charset=UTF-8');
res.end(response);
}, 10000);
}).listen(4444, () => {
StellarSdk.StellarTomlResolver.resolve("localhost:4444", {allowHttp: true, timeout: 100})
.should.be.rejectedWith(/timeout of 100ms exceeded/)
.notify(done)
.then(() => tempServer.close());
});
});
});
});

0 comments on commit 8ff7e75

Please sign in to comment.