From b5c762848fb472afba99b3570cdcab3d363cb18b Mon Sep 17 00:00:00 2001 From: Grant Herman Date: Wed, 27 Feb 2019 17:34:22 -0800 Subject: [PATCH 1/5] feat(issue-1852): now supports multiple api and gateways License: MIT Signed-off-by: Grant Herman grantlouisherman041@gmail.com --- src/http/index.js | 61 ++++++++++++++++++++++--------- test/gateway/index.js | 2 +- test/http-api/inject/bitswap.js | 2 +- test/http-api/inject/block.js | 2 +- test/http-api/inject/bootstrap.js | 2 +- test/http-api/inject/config.js | 2 +- test/http-api/inject/dht.js | 2 +- test/http-api/inject/dns.js | 2 +- test/http-api/inject/files.js | 2 +- test/http-api/inject/id.js | 2 +- test/http-api/inject/name.js | 2 +- test/http-api/inject/object.js | 2 +- test/http-api/inject/pin.js | 2 +- test/http-api/inject/ping.js | 2 +- test/http-api/inject/pubsub.js | 2 +- test/http-api/inject/resolve.js | 2 +- test/http-api/inject/version.js | 2 +- 17 files changed, 60 insertions(+), 33 deletions(-) diff --git a/src/http/index.js b/src/http/index.js index c0de7a642e..4a2fb531c9 100644 --- a/src/http/index.js +++ b/src/http/index.js @@ -29,6 +29,24 @@ function hapiInfoToMultiaddr (info) { return toMultiaddr(uri) } +async function serverCreator (serverAddrsArr, createServerFunc, hapiInfoToMultiaddr, ipfs) { + if (!serverAddrsArr.length) { + debug(Error('There are no addresses')) + } + // just in case the address is just string + let serversAddrs = [].concat(serverAddrsArr) + const processServer = async (serverInstance, createServerFunc, hapiInfoToMultiaddr, ipfs) => { + let addr = serverInstance.split('/') + let _Server = await createServerFunc(addr[2], addr[4], ipfs) + await _Server.start() + _Server.info.ma = hapiInfoToMultiaddr(_Server.info) + return _Server + } + return Promise.all( + serversAddrs.map(server => processServer(server, createServerFunc, hapiInfoToMultiaddr, ipfs)) + ).catch(err => debug(err)) +} + class HttpApi { constructor (options) { this._options = options || {} @@ -89,24 +107,28 @@ class HttpApi { const config = await ipfs.config.get() - const apiAddr = config.Addresses.API.split('/') - const apiServer = await this._createApiServer(apiAddr[2], apiAddr[4], ipfs) - await apiServer.start() - apiServer.info.ma = hapiInfoToMultiaddr(apiServer.info) - this._apiServer = apiServer + const apiAddrs = config.Addresses.API + this._apiServer = await Promise.resolve( + serverCreator.apply(this, [apiAddrs, this._createApiServer, hapiInfoToMultiaddr, ipfs]) + ) // for the CLI to know the where abouts of the API - await promisify(ipfs._repo.apiAddr.set)(apiServer.info.ma) + await promisify(ipfs._repo.apiAddr.set)(this._apiServer[0].info.ma) - const gatewayAddr = config.Addresses.Gateway.split('/') - const gatewayServer = await this._createGatewayServer(gatewayAddr[2], gatewayAddr[4], ipfs) - await gatewayServer.start() - gatewayServer.info.ma = hapiInfoToMultiaddr(gatewayServer.info) - this._gatewayServer = gatewayServer + const gatewayAddr = config.Addresses.Gateway - ipfs._print('API listening on %s', apiServer.info.ma) - ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma) - ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui') + this._gatewayServer = await Promise.resolve( + serverCreator.apply(this, [gatewayAddr, this._createGatewayServer, hapiInfoToMultiaddr, ipfs]) + ) + this._apiServer.forEach(apiServer => { + ipfs._print('API listening on %s', apiServer.info.ma) + }) + this._gatewayServer.forEach(gatewayServer => { + ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma) + }) + this._apiServer.forEach(apiServer => { + ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui') + }) this._log('started') return this } @@ -177,14 +199,19 @@ class HttpApi { get apiAddr () { if (!this._apiServer) throw new Error('API address unavailable - server is not started') - return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServer.info.port) + return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServer[0].info.port) } async stop () { + function stopServer (serverArr) { + for (let i = 0; i < serverArr.length; i++) { + serverArr[i].stop() + } + } this._log('stopping') await Promise.all([ - this._apiServer && this._apiServer.stop(), - this._gatewayServer && this._gatewayServer.stop(), + this._apiServer && stopServer(this._apiServer), + this._gatewayServer && stopServer(this._gatewayServer), this._ipfs && this._ipfs.stop() ]) this._log('stopped') diff --git a/test/gateway/index.js b/test/gateway/index.js index 0f9ac1812b..847e8b5846 100644 --- a/test/gateway/index.js +++ b/test/gateway/index.js @@ -60,7 +60,7 @@ describe('HTTP Gateway', function () { await http.api.start() - gateway = http.api._gatewayServer + gateway = http.api._gatewayServer[0] // QmbQD7EMEL1zeebwBsWEfA3ndgSS6F7S6iTuwuqasPgVRi await http.api._ipfs.add([ diff --git a/test/http-api/inject/bitswap.js b/test/http-api/inject/bitswap.js index c8a1d0568c..7e2fa0a16f 100644 --- a/test/http-api/inject/bitswap.js +++ b/test/http-api/inject/bitswap.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) before(async function () { diff --git a/test/http-api/inject/block.js b/test/http-api/inject/block.js index 1cf8eb52e4..8d4ddc0b49 100644 --- a/test/http-api/inject/block.js +++ b/test/http-api/inject/block.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('/block/put', () => { diff --git a/test/http-api/inject/bootstrap.js b/test/http-api/inject/bootstrap.js index 7708390cfe..22e19160e7 100644 --- a/test/http-api/inject/bootstrap.js +++ b/test/http-api/inject/bootstrap.js @@ -11,7 +11,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] return api.inject({ method: 'GET', url: '/api/v0/bootstrap/add/default' diff --git a/test/http-api/inject/config.js b/test/http-api/inject/config.js index 3e647505ff..aa75e1f861 100644 --- a/test/http-api/inject/config.js +++ b/test/http-api/inject/config.js @@ -17,7 +17,7 @@ module.exports = (http) => { before(() => { updatedConfig = () => JSON.parse(fs.readFileSync(configPath, 'utf8')) - api = http.api._apiServer + api = http.api._apiServer[0] }) after(() => { diff --git a/test/http-api/inject/dht.js b/test/http-api/inject/dht.js index f614ee50dc..949645836b 100644 --- a/test/http-api/inject/dht.js +++ b/test/http-api/inject/dht.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('/findpeer', () => { diff --git a/test/http-api/inject/dns.js b/test/http-api/inject/dns.js index 163f2dfd4f..51ac1e3218 100644 --- a/test/http-api/inject/dns.js +++ b/test/http-api/inject/dns.js @@ -8,7 +8,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('resolve ipfs.io dns', async () => { diff --git a/test/http-api/inject/files.js b/test/http-api/inject/files.js index 06d2e02597..b6a03ff5a2 100644 --- a/test/http-api/inject/files.js +++ b/test/http-api/inject/files.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('/add', () => { diff --git a/test/http-api/inject/id.js b/test/http-api/inject/id.js index eb646be893..79aeccbc5c 100644 --- a/test/http-api/inject/id.js +++ b/test/http-api/inject/id.js @@ -8,7 +8,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('get the id', async () => { diff --git a/test/http-api/inject/name.js b/test/http-api/inject/name.js index 95a51eb5c2..bfd693e3cb 100644 --- a/test/http-api/inject/name.js +++ b/test/http-api/inject/name.js @@ -16,7 +16,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('should publish a record', async function () { diff --git a/test/http-api/inject/object.js b/test/http-api/inject/object.js index e329e98c64..2505718852 100644 --- a/test/http-api/inject/object.js +++ b/test/http-api/inject/object.js @@ -17,7 +17,7 @@ module.exports = (http) => { let api before('api', () => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('/new', () => { diff --git a/test/http-api/inject/pin.js b/test/http-api/inject/pin.js index d70547a876..c950a68d24 100644 --- a/test/http-api/inject/pin.js +++ b/test/http-api/inject/pin.js @@ -37,7 +37,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('rm', () => { diff --git a/test/http-api/inject/ping.js b/test/http-api/inject/ping.js index 0ed460bba3..3982b9f09b 100644 --- a/test/http-api/inject/ping.js +++ b/test/http-api/inject/ping.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('returns 400 if both n and count are provided', async () => { diff --git a/test/http-api/inject/pubsub.js b/test/http-api/inject/pubsub.js index e91df8b3a3..5b613929f3 100644 --- a/test/http-api/inject/pubsub.js +++ b/test/http-api/inject/pubsub.js @@ -16,7 +16,7 @@ module.exports = (http) => { const topicNotSubscribed = 'somethingRandom' before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) describe('/sub', () => { diff --git a/test/http-api/inject/resolve.js b/test/http-api/inject/resolve.js index edb7eb94ab..39f3b28f39 100644 --- a/test/http-api/inject/resolve.js +++ b/test/http-api/inject/resolve.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('should resolve a path and return a base2 encoded CID', async () => { diff --git a/test/http-api/inject/version.js b/test/http-api/inject/version.js index 2ab6b18bf9..07645d942c 100644 --- a/test/http-api/inject/version.js +++ b/test/http-api/inject/version.js @@ -9,7 +9,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer + api = http.api._apiServer[0] }) it('get the version', async () => { From 1b17688d63326d25b8ef553865937f7a1c53edd3 Mon Sep 17 00:00:00 2001 From: Grant Herman Date: Wed, 6 Mar 2019 17:31:34 -0800 Subject: [PATCH 2/5] feat(pr): addressing PR comments --- src/http/index.js | 58 ++++++++++++++----------------- test/cli/daemon.js | 29 +++++++++++++++- test/gateway/index.js | 2 +- test/http-api/inject/bitswap.js | 2 +- test/http-api/inject/block.js | 2 +- test/http-api/inject/bootstrap.js | 2 +- test/http-api/inject/config.js | 2 +- test/http-api/inject/dht.js | 2 +- test/http-api/inject/dns.js | 2 +- test/http-api/inject/files.js | 2 +- test/http-api/inject/id.js | 2 +- test/http-api/inject/name.js | 2 +- test/http-api/inject/object.js | 2 +- test/http-api/inject/pin.js | 2 +- test/http-api/inject/ping.js | 2 +- test/http-api/inject/pubsub.js | 2 +- test/http-api/inject/resolve.js | 2 +- test/http-api/inject/version.js | 2 +- 18 files changed, 70 insertions(+), 49 deletions(-) diff --git a/src/http/index.js b/src/http/index.js index 4a2fb531c9..158380117f 100644 --- a/src/http/index.js +++ b/src/http/index.js @@ -29,22 +29,20 @@ function hapiInfoToMultiaddr (info) { return toMultiaddr(uri) } -async function serverCreator (serverAddrsArr, createServerFunc, hapiInfoToMultiaddr, ipfs) { - if (!serverAddrsArr.length) { - debug(Error('There are no addresses')) +async function serverCreator (serverAddrs, createServer, hapiInfoToMultiaddr, ipfs) { + if (!serverAddrs.length) { + return [] } // just in case the address is just string - let serversAddrs = [].concat(serverAddrsArr) - const processServer = async (serverInstance, createServerFunc, hapiInfoToMultiaddr, ipfs) => { - let addr = serverInstance.split('/') - let _Server = await createServerFunc(addr[2], addr[4], ipfs) - await _Server.start() - _Server.info.ma = hapiInfoToMultiaddr(_Server.info) - return _Server + serverAddrs = Array.isArray(serverAddrs) ? serverAddrs : [serverAddrs] + const processServer = async address => { + const addrParts = address.split('/') + const server = await createServer(addrParts[2], addrParts[4], ipfs) + await server.start() + server.info.ma = hapiInfoToMultiaddr(server.info) + return server } - return Promise.all( - serversAddrs.map(server => processServer(server, createServerFunc, hapiInfoToMultiaddr, ipfs)) - ).catch(err => debug(err)) + return Promise.all(serverAddrs.map(processServer)) } class HttpApi { @@ -109,24 +107,22 @@ class HttpApi { const apiAddrs = config.Addresses.API - this._apiServer = await Promise.resolve( - serverCreator.apply(this, [apiAddrs, this._createApiServer, hapiInfoToMultiaddr, ipfs]) - ) + this._apiServers = await serverCreator(apiAddrs, this._createApiServer, hapiInfoToMultiaddr, ipfs) + // for the CLI to know the where abouts of the API - await promisify(ipfs._repo.apiAddr.set)(this._apiServer[0].info.ma) + await promisify(ipfs._repo.apiAddr.set)(this._apiServers[0].info.ma) - const gatewayAddr = config.Addresses.Gateway + const gatewayAddrs = config.Addresses.Gateway - this._gatewayServer = await Promise.resolve( - serverCreator.apply(this, [gatewayAddr, this._createGatewayServer, hapiInfoToMultiaddr, ipfs]) - ) - this._apiServer.forEach(apiServer => { + this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, hapiInfoToMultiaddr, ipfs) + + this._apiServers.forEach(apiServer => { ipfs._print('API listening on %s', apiServer.info.ma) }) - this._gatewayServer.forEach(gatewayServer => { + this._gatewayServers.forEach(gatewayServer => { ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma) }) - this._apiServer.forEach(apiServer => { + this._apiServers.forEach(apiServer => { ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui') }) this._log('started') @@ -198,20 +194,18 @@ class HttpApi { } get apiAddr () { - if (!this._apiServer) throw new Error('API address unavailable - server is not started') - return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServer[0].info.port) + if (!this._apiServers) throw new Error('API address unavailable - server is not started') + return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port) } async stop () { - function stopServer (serverArr) { - for (let i = 0; i < serverArr.length; i++) { - serverArr[i].stop() - } + function stopServers (servers) { + return Promise.all(servers.map(server => server.stop())) } this._log('stopping') await Promise.all([ - this._apiServer && stopServer(this._apiServer), - this._gatewayServer && stopServer(this._gatewayServer), + stopServers(this._apiServers), + stopServers(this._gatewayServers), this._ipfs && this._ipfs.stop() ]) this._log('stopped') diff --git a/test/cli/daemon.js b/test/cli/daemon.js index a9aaccacf0..3a42d20f12 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -26,7 +26,7 @@ const checkLock = (repo, cb) => { cb() } -function testSignal (ipfs, sig) { +function testSignal (ipfs, sig, config) { return ipfs('init').then(() => { return ipfs('config', 'Addresses', JSON.stringify({ API: '/ip4/127.0.0.1/tcp/0', @@ -91,6 +91,33 @@ describe('daemon', () => { }).catch(err => done(err)) }) + skipOnWindows('should handle API Array and Gateway Array', function (done) { + this.timeout(100 * 1000) + // These tests are flaky, but retrying 3 times seems to make it work 99% of the time + this.retries(3) + + ipfs('init').then(() => { + return ipfs('config', 'Addresses', JSON.stringify({ + Swarm: ['/ip4/0.0.0.0/tcp/4002', '/ip4/127.0.0.1/tcp/4003/ws'], + API: ['/ip4/127.0.0.1/tcp/5002', '/ip6/::1/tcp/5002'], + Gateway: ['/ip4/127.0.0.1/tcp/9090', '/ip6/::1/tcp/9090'] + }), '--json') + }).then(() => { + const res = ipfs('daemon') + const timeout = setTimeout(() => { + done(new Error('Daemon did not get ready in time')) + }, 1000 * 120) + res.stdout.on('data', (data) => { + const line = data.toString() + if (line.includes('Daemon is ready')) { + clearTimeout(timeout) + res.kill() + done() + } + }) + }).catch(err => done(err)) + }) + skipOnWindows('should handle SIGINT gracefully', function (done) { this.timeout(100 * 1000) diff --git a/test/gateway/index.js b/test/gateway/index.js index 847e8b5846..c5f9bd0be6 100644 --- a/test/gateway/index.js +++ b/test/gateway/index.js @@ -60,7 +60,7 @@ describe('HTTP Gateway', function () { await http.api.start() - gateway = http.api._gatewayServer[0] + gateway = http.api._gatewayServers[0] // QmbQD7EMEL1zeebwBsWEfA3ndgSS6F7S6iTuwuqasPgVRi await http.api._ipfs.add([ diff --git a/test/http-api/inject/bitswap.js b/test/http-api/inject/bitswap.js index 7e2fa0a16f..9ac273c947 100644 --- a/test/http-api/inject/bitswap.js +++ b/test/http-api/inject/bitswap.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) before(async function () { diff --git a/test/http-api/inject/block.js b/test/http-api/inject/block.js index 8d4ddc0b49..a121fc315d 100644 --- a/test/http-api/inject/block.js +++ b/test/http-api/inject/block.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('/block/put', () => { diff --git a/test/http-api/inject/bootstrap.js b/test/http-api/inject/bootstrap.js index 22e19160e7..5015b3d40f 100644 --- a/test/http-api/inject/bootstrap.js +++ b/test/http-api/inject/bootstrap.js @@ -11,7 +11,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] return api.inject({ method: 'GET', url: '/api/v0/bootstrap/add/default' diff --git a/test/http-api/inject/config.js b/test/http-api/inject/config.js index aa75e1f861..2388ed4264 100644 --- a/test/http-api/inject/config.js +++ b/test/http-api/inject/config.js @@ -17,7 +17,7 @@ module.exports = (http) => { before(() => { updatedConfig = () => JSON.parse(fs.readFileSync(configPath, 'utf8')) - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) after(() => { diff --git a/test/http-api/inject/dht.js b/test/http-api/inject/dht.js index 949645836b..04cb501227 100644 --- a/test/http-api/inject/dht.js +++ b/test/http-api/inject/dht.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('/findpeer', () => { diff --git a/test/http-api/inject/dns.js b/test/http-api/inject/dns.js index 51ac1e3218..010797f57a 100644 --- a/test/http-api/inject/dns.js +++ b/test/http-api/inject/dns.js @@ -8,7 +8,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('resolve ipfs.io dns', async () => { diff --git a/test/http-api/inject/files.js b/test/http-api/inject/files.js index b6a03ff5a2..8ff819dfce 100644 --- a/test/http-api/inject/files.js +++ b/test/http-api/inject/files.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('/add', () => { diff --git a/test/http-api/inject/id.js b/test/http-api/inject/id.js index 79aeccbc5c..ff8922f312 100644 --- a/test/http-api/inject/id.js +++ b/test/http-api/inject/id.js @@ -8,7 +8,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('get the id', async () => { diff --git a/test/http-api/inject/name.js b/test/http-api/inject/name.js index bfd693e3cb..699ed0a07b 100644 --- a/test/http-api/inject/name.js +++ b/test/http-api/inject/name.js @@ -16,7 +16,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('should publish a record', async function () { diff --git a/test/http-api/inject/object.js b/test/http-api/inject/object.js index 2505718852..952cf1ab7d 100644 --- a/test/http-api/inject/object.js +++ b/test/http-api/inject/object.js @@ -17,7 +17,7 @@ module.exports = (http) => { let api before('api', () => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('/new', () => { diff --git a/test/http-api/inject/pin.js b/test/http-api/inject/pin.js index c950a68d24..db1ec00b6c 100644 --- a/test/http-api/inject/pin.js +++ b/test/http-api/inject/pin.js @@ -37,7 +37,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('rm', () => { diff --git a/test/http-api/inject/ping.js b/test/http-api/inject/ping.js index 3982b9f09b..3ed712c483 100644 --- a/test/http-api/inject/ping.js +++ b/test/http-api/inject/ping.js @@ -13,7 +13,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('returns 400 if both n and count are provided', async () => { diff --git a/test/http-api/inject/pubsub.js b/test/http-api/inject/pubsub.js index 5b613929f3..3e88d40434 100644 --- a/test/http-api/inject/pubsub.js +++ b/test/http-api/inject/pubsub.js @@ -16,7 +16,7 @@ module.exports = (http) => { const topicNotSubscribed = 'somethingRandom' before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) describe('/sub', () => { diff --git a/test/http-api/inject/resolve.js b/test/http-api/inject/resolve.js index 39f3b28f39..1d70206e8a 100644 --- a/test/http-api/inject/resolve.js +++ b/test/http-api/inject/resolve.js @@ -12,7 +12,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('should resolve a path and return a base2 encoded CID', async () => { diff --git a/test/http-api/inject/version.js b/test/http-api/inject/version.js index 07645d942c..9a83821ebe 100644 --- a/test/http-api/inject/version.js +++ b/test/http-api/inject/version.js @@ -9,7 +9,7 @@ module.exports = (http) => { let api before(() => { - api = http.api._apiServer[0] + api = http.api._apiServers[0] }) it('get the version', async () => { From e57d0e96b693c7a4600fd9de7775a3dc164fea59 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 11 Mar 2019 13:58:12 +0000 Subject: [PATCH 3/5] refactor: cleanup and add test License: MIT Signed-off-by: Alan Shaw --- src/http/index.js | 25 ++++++++--------- test/cli/daemon.js | 69 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/http/index.js b/src/http/index.js index 158380117f..38f9d1138b 100644 --- a/src/http/index.js +++ b/src/http/index.js @@ -29,12 +29,11 @@ function hapiInfoToMultiaddr (info) { return toMultiaddr(uri) } -async function serverCreator (serverAddrs, createServer, hapiInfoToMultiaddr, ipfs) { - if (!serverAddrs.length) { - return [] - } +function serverCreator (serverAddrs, createServer, ipfs) { + serverAddrs = serverAddrs || [] // just in case the address is just string serverAddrs = Array.isArray(serverAddrs) ? serverAddrs : [serverAddrs] + const processServer = async address => { const addrParts = address.split('/') const server = await createServer(addrParts[2], addrParts[4], ipfs) @@ -42,6 +41,7 @@ async function serverCreator (serverAddrs, createServer, hapiInfoToMultiaddr, ip server.info.ma = hapiInfoToMultiaddr(server.info) return server } + return Promise.all(serverAddrs.map(processServer)) } @@ -104,17 +104,18 @@ class HttpApi { this._ipfs = ipfs const config = await ipfs.config.get() + config.Addresses = config.Addresses || {} const apiAddrs = config.Addresses.API - - this._apiServers = await serverCreator(apiAddrs, this._createApiServer, hapiInfoToMultiaddr, ipfs) + this._apiServers = await serverCreator(apiAddrs, this._createApiServer, ipfs) // for the CLI to know the where abouts of the API - await promisify(ipfs._repo.apiAddr.set)(this._apiServers[0].info.ma) + if (this._apiServers.length) { + await promisify(ipfs._repo.apiAddr.set)(this._apiServers[0].info.ma) + } const gatewayAddrs = config.Addresses.Gateway - - this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, hapiInfoToMultiaddr, ipfs) + this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, ipfs) this._apiServers.forEach(apiServer => { ipfs._print('API listening on %s', apiServer.info.ma) @@ -194,15 +195,13 @@ class HttpApi { } get apiAddr () { - if (!this._apiServers) throw new Error('API address unavailable - server is not started') + if (!this._apiServers.length) throw new Error('API address unavailable - server is not started') return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port) } async stop () { - function stopServers (servers) { - return Promise.all(servers.map(server => server.stop())) - } this._log('stopping') + const stopServers = servers => Promise.all((servers || []).map(s => s.stop())) await Promise.all([ stopServers(this._apiServers), stopServers(this._gatewayServers), diff --git a/test/cli/daemon.js b/test/cli/daemon.js index 3a42d20f12..e46d8835a3 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -91,31 +91,60 @@ describe('daemon', () => { }).catch(err => done(err)) }) - skipOnWindows('should handle API Array and Gateway Array', function (done) { - this.timeout(100 * 1000) - // These tests are flaky, but retrying 3 times seems to make it work 99% of the time - this.retries(3) + it('should allow bind to multiple addresses for API and Gateway', async () => { + const apiAddrs = [ + '/ip4/127.0.0.1/tcp/55001', + '/ip4/127.0.0.1/tcp/55002' + ] + + const gatewayAddrs = [ + '/ip4/127.0.0.1/tcp/64080', + '/ip4/127.0.0.1/tcp/64081' + ] + + await ipfs('init') + await ipfs('config', 'Addresses.API', JSON.stringify(apiAddrs), '--json') + await ipfs('config', 'Addresses.Gateway', JSON.stringify(gatewayAddrs), '--json') + + const out = await new Promise(resolve => { + const res = ipfs('daemon') + let out = '' - ipfs('init').then(() => { - return ipfs('config', 'Addresses', JSON.stringify({ - Swarm: ['/ip4/0.0.0.0/tcp/4002', '/ip4/127.0.0.1/tcp/4003/ws'], - API: ['/ip4/127.0.0.1/tcp/5002', '/ip6/::1/tcp/5002'], - Gateway: ['/ip4/127.0.0.1/tcp/9090', '/ip6/::1/tcp/9090'] - }), '--json') - }).then(() => { + res.stdout.on('data', function onData (data) { + out += data + if (out.includes('Daemon is ready')) { + res.stdout.removeListener('data', onData) + res.kill() + resolve(out) + } + }) + }) + + apiAddrs.forEach(addr => expect(out).to.include(`API listening on ${addr}`)) + gatewayAddrs.forEach(addr => expect(out).to.include(`Gateway (read only) listening on ${addr}`)) + }) + + it('should allow no bind addresses for API and Gateway', async () => { + await ipfs('init') + await ipfs('config', 'Addresses.API', '[]', '--json') + await ipfs('config', 'Addresses.Gateway', '[]', '--json') + + const out = await new Promise(resolve => { const res = ipfs('daemon') - const timeout = setTimeout(() => { - done(new Error('Daemon did not get ready in time')) - }, 1000 * 120) - res.stdout.on('data', (data) => { - const line = data.toString() - if (line.includes('Daemon is ready')) { - clearTimeout(timeout) + let out = '' + + res.stdout.on('data', function onData (data) { + out += data + if (out.includes('Daemon is ready')) { + res.stdout.removeListener('data', onData) res.kill() - done() + resolve(out) } }) - }).catch(err => done(err)) + }) + + expect(out).to.not.include('API listening on') + expect(out).to.not.include('Gateway (read only) listening on') }) skipOnWindows('should handle SIGINT gracefully', function (done) { From 1c382024511d3ff2ea0d9d4aead142ac3c2c82a7 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 11 Mar 2019 14:00:57 +0000 Subject: [PATCH 4/5] fix: guard against undefined _apiServers License: MIT Signed-off-by: Alan Shaw --- src/http/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/http/index.js b/src/http/index.js index 38f9d1138b..3f77bfbf7b 100644 --- a/src/http/index.js +++ b/src/http/index.js @@ -195,7 +195,9 @@ class HttpApi { } get apiAddr () { - if (!this._apiServers.length) throw new Error('API address unavailable - server is not started') + if (!this._apiServers || !this._apiServers.length) { + throw new Error('API address unavailable - server is not started') + } return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port) } From d5215c2d8e33ade066d437069e7200db785affa2 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Mon, 11 Mar 2019 15:02:32 +0000 Subject: [PATCH 5/5] chore: increase timeout for windows License: MIT Signed-off-by: Alan Shaw --- test/cli/daemon.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/cli/daemon.js b/test/cli/daemon.js index e46d8835a3..5e9efe08d8 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -91,7 +91,9 @@ describe('daemon', () => { }).catch(err => done(err)) }) - it('should allow bind to multiple addresses for API and Gateway', async () => { + it('should allow bind to multiple addresses for API and Gateway', async function () { + this.timeout(20 * 1000) + const apiAddrs = [ '/ip4/127.0.0.1/tcp/55001', '/ip4/127.0.0.1/tcp/55002' @@ -124,7 +126,9 @@ describe('daemon', () => { gatewayAddrs.forEach(addr => expect(out).to.include(`Gateway (read only) listening on ${addr}`)) }) - it('should allow no bind addresses for API and Gateway', async () => { + it('should allow no bind addresses for API and Gateway', async function () { + this.timeout(20 * 1000) + await ipfs('init') await ipfs('config', 'Addresses.API', '[]', '--json') await ipfs('config', 'Addresses.Gateway', '[]', '--json')