Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
feat(issue-1852): support multiple API and Gateway addresses (#1903)
Browse files Browse the repository at this point in the history
resolves #1852

License: MIT
Signed-off-by: Grant Herman [email protected]
  • Loading branch information
grantlouisherman authored and Alan Shaw committed Mar 11, 2019
1 parent d2726fb commit 4ad104d
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 35 deletions.
58 changes: 40 additions & 18 deletions src/http/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@ function hapiInfoToMultiaddr (info) {
return toMultiaddr(uri)
}

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)
await server.start()
server.info.ma = hapiInfoToMultiaddr(server.info)
return server
}

return Promise.all(serverAddrs.map(processServer))
}

class HttpApi {
constructor (options) {
this._options = options || {}
Expand Down Expand Up @@ -88,25 +104,28 @@ class HttpApi {
this._ipfs = ipfs

const config = await ipfs.config.get()
config.Addresses = config.Addresses || {}

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._apiServers = await serverCreator(apiAddrs, this._createApiServer, ipfs)

// for the CLI to know the where abouts of the API
await promisify(ipfs._repo.apiAddr.set)(apiServer.info.ma)
if (this._apiServers.length) {
await promisify(ipfs._repo.apiAddr.set)(this._apiServers[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 gatewayAddrs = config.Addresses.Gateway
this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, ipfs)

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._apiServers.forEach(apiServer => {
ipfs._print('API listening on %s', apiServer.info.ma)
})
this._gatewayServers.forEach(gatewayServer => {
ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma)
})
this._apiServers.forEach(apiServer => {
ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui')
})
this._log('started')
return this
}
Expand Down Expand Up @@ -176,15 +195,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.info.port)
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)
}

async stop () {
this._log('stopping')
const stopServers = servers => Promise.all((servers || []).map(s => s.stop()))
await Promise.all([
this._apiServer && this._apiServer.stop(),
this._gatewayServer && this._gatewayServer.stop(),
stopServers(this._apiServers),
stopServers(this._gatewayServers),
this._ipfs && this._ipfs.stop()
])
this._log('stopped')
Expand Down
62 changes: 61 additions & 1 deletion test/cli/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -91,6 +91,66 @@ describe('daemon', () => {
}).catch(err => done(err))
})

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'
]

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 = ''

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 function () {
this.timeout(20 * 1000)

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')
let out = ''

res.stdout.on('data', function onData (data) {
out += data
if (out.includes('Daemon is ready')) {
res.stdout.removeListener('data', onData)
res.kill()
resolve(out)
}
})
})

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) {
this.timeout(100 * 1000)

Expand Down
2 changes: 1 addition & 1 deletion test/gateway/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('HTTP Gateway', function () {

await http.api.start()

gateway = http.api._gatewayServer
gateway = http.api._gatewayServers[0]

// QmbQD7EMEL1zeebwBsWEfA3ndgSS6F7S6iTuwuqasPgVRi
await http.api._ipfs.add([
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/bitswap.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

before(async function () {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('/block/put', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
return api.inject({
method: 'GET',
url: '/api/v0/bootstrap/add/default'
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = (http) => {

before(() => {
updatedConfig = () => JSON.parse(fs.readFileSync(configPath, 'utf8'))
api = http.api._apiServer
api = http.api._apiServers[0]
})

after(() => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/dht.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('/findpeer', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('resolve ipfs.io dns', async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('/add', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('get the id', async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/name.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('should publish a record', async function () {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = (http) => {
let api

before('api', () => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('/new', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/pin.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('rm', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/ping.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('returns 400 if both n and count are provided', async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = (http) => {
const topicNotSubscribed = 'somethingRandom'

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

describe('/sub', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('should resolve a path and return a base2 encoded CID', async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/http-api/inject/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = (http) => {
let api

before(() => {
api = http.api._apiServer
api = http.api._apiServers[0]
})

it('get the version', async () => {
Expand Down

0 comments on commit 4ad104d

Please sign in to comment.