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

Commit 4ad104d

Browse files
grantlouishermanAlan Shaw
authored and
Alan Shaw
committed
feat(issue-1852): support multiple API and Gateway addresses (#1903)
resolves #1852 License: MIT Signed-off-by: Grant Herman [email protected]
1 parent d2726fb commit 4ad104d

18 files changed

+117
-35
lines changed

src/http/index.js

+40-18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ function hapiInfoToMultiaddr (info) {
2929
return toMultiaddr(uri)
3030
}
3131

32+
function serverCreator (serverAddrs, createServer, ipfs) {
33+
serverAddrs = serverAddrs || []
34+
// just in case the address is just string
35+
serverAddrs = Array.isArray(serverAddrs) ? serverAddrs : [serverAddrs]
36+
37+
const processServer = async address => {
38+
const addrParts = address.split('/')
39+
const server = await createServer(addrParts[2], addrParts[4], ipfs)
40+
await server.start()
41+
server.info.ma = hapiInfoToMultiaddr(server.info)
42+
return server
43+
}
44+
45+
return Promise.all(serverAddrs.map(processServer))
46+
}
47+
3248
class HttpApi {
3349
constructor (options) {
3450
this._options = options || {}
@@ -88,25 +104,28 @@ class HttpApi {
88104
this._ipfs = ipfs
89105

90106
const config = await ipfs.config.get()
107+
config.Addresses = config.Addresses || {}
91108

92-
const apiAddr = config.Addresses.API.split('/')
93-
const apiServer = await this._createApiServer(apiAddr[2], apiAddr[4], ipfs)
94-
await apiServer.start()
95-
apiServer.info.ma = hapiInfoToMultiaddr(apiServer.info)
96-
this._apiServer = apiServer
109+
const apiAddrs = config.Addresses.API
110+
this._apiServers = await serverCreator(apiAddrs, this._createApiServer, ipfs)
97111

98112
// for the CLI to know the where abouts of the API
99-
await promisify(ipfs._repo.apiAddr.set)(apiServer.info.ma)
113+
if (this._apiServers.length) {
114+
await promisify(ipfs._repo.apiAddr.set)(this._apiServers[0].info.ma)
115+
}
100116

101-
const gatewayAddr = config.Addresses.Gateway.split('/')
102-
const gatewayServer = await this._createGatewayServer(gatewayAddr[2], gatewayAddr[4], ipfs)
103-
await gatewayServer.start()
104-
gatewayServer.info.ma = hapiInfoToMultiaddr(gatewayServer.info)
105-
this._gatewayServer = gatewayServer
117+
const gatewayAddrs = config.Addresses.Gateway
118+
this._gatewayServers = await serverCreator(gatewayAddrs, this._createGatewayServer, ipfs)
106119

107-
ipfs._print('API listening on %s', apiServer.info.ma)
108-
ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma)
109-
ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui')
120+
this._apiServers.forEach(apiServer => {
121+
ipfs._print('API listening on %s', apiServer.info.ma)
122+
})
123+
this._gatewayServers.forEach(gatewayServer => {
124+
ipfs._print('Gateway (read only) listening on %s', gatewayServer.info.ma)
125+
})
126+
this._apiServers.forEach(apiServer => {
127+
ipfs._print('Web UI available at %s', toUri(apiServer.info.ma) + '/webui')
128+
})
110129
this._log('started')
111130
return this
112131
}
@@ -176,15 +195,18 @@ class HttpApi {
176195
}
177196

178197
get apiAddr () {
179-
if (!this._apiServer) throw new Error('API address unavailable - server is not started')
180-
return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServer.info.port)
198+
if (!this._apiServers || !this._apiServers.length) {
199+
throw new Error('API address unavailable - server is not started')
200+
}
201+
return multiaddr('/ip4/127.0.0.1/tcp/' + this._apiServers[0].info.port)
181202
}
182203

183204
async stop () {
184205
this._log('stopping')
206+
const stopServers = servers => Promise.all((servers || []).map(s => s.stop()))
185207
await Promise.all([
186-
this._apiServer && this._apiServer.stop(),
187-
this._gatewayServer && this._gatewayServer.stop(),
208+
stopServers(this._apiServers),
209+
stopServers(this._gatewayServers),
188210
this._ipfs && this._ipfs.stop()
189211
])
190212
this._log('stopped')

test/cli/daemon.js

+61-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const checkLock = (repo, cb) => {
2626
cb()
2727
}
2828

29-
function testSignal (ipfs, sig) {
29+
function testSignal (ipfs, sig, config) {
3030
return ipfs('init').then(() => {
3131
return ipfs('config', 'Addresses', JSON.stringify({
3232
API: '/ip4/127.0.0.1/tcp/0',
@@ -91,6 +91,66 @@ describe('daemon', () => {
9191
}).catch(err => done(err))
9292
})
9393

94+
it('should allow bind to multiple addresses for API and Gateway', async function () {
95+
this.timeout(20 * 1000)
96+
97+
const apiAddrs = [
98+
'/ip4/127.0.0.1/tcp/55001',
99+
'/ip4/127.0.0.1/tcp/55002'
100+
]
101+
102+
const gatewayAddrs = [
103+
'/ip4/127.0.0.1/tcp/64080',
104+
'/ip4/127.0.0.1/tcp/64081'
105+
]
106+
107+
await ipfs('init')
108+
await ipfs('config', 'Addresses.API', JSON.stringify(apiAddrs), '--json')
109+
await ipfs('config', 'Addresses.Gateway', JSON.stringify(gatewayAddrs), '--json')
110+
111+
const out = await new Promise(resolve => {
112+
const res = ipfs('daemon')
113+
let out = ''
114+
115+
res.stdout.on('data', function onData (data) {
116+
out += data
117+
if (out.includes('Daemon is ready')) {
118+
res.stdout.removeListener('data', onData)
119+
res.kill()
120+
resolve(out)
121+
}
122+
})
123+
})
124+
125+
apiAddrs.forEach(addr => expect(out).to.include(`API listening on ${addr}`))
126+
gatewayAddrs.forEach(addr => expect(out).to.include(`Gateway (read only) listening on ${addr}`))
127+
})
128+
129+
it('should allow no bind addresses for API and Gateway', async function () {
130+
this.timeout(20 * 1000)
131+
132+
await ipfs('init')
133+
await ipfs('config', 'Addresses.API', '[]', '--json')
134+
await ipfs('config', 'Addresses.Gateway', '[]', '--json')
135+
136+
const out = await new Promise(resolve => {
137+
const res = ipfs('daemon')
138+
let out = ''
139+
140+
res.stdout.on('data', function onData (data) {
141+
out += data
142+
if (out.includes('Daemon is ready')) {
143+
res.stdout.removeListener('data', onData)
144+
res.kill()
145+
resolve(out)
146+
}
147+
})
148+
})
149+
150+
expect(out).to.not.include('API listening on')
151+
expect(out).to.not.include('Gateway (read only) listening on')
152+
})
153+
94154
skipOnWindows('should handle SIGINT gracefully', function (done) {
95155
this.timeout(100 * 1000)
96156

test/gateway/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('HTTP Gateway', function () {
6060

6161
await http.api.start()
6262

63-
gateway = http.api._gatewayServer
63+
gateway = http.api._gatewayServers[0]
6464

6565
// QmbQD7EMEL1zeebwBsWEfA3ndgSS6F7S6iTuwuqasPgVRi
6666
await http.api._ipfs.add([

test/http-api/inject/bitswap.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = (http) => {
1212
let api
1313

1414
before(() => {
15-
api = http.api._apiServer
15+
api = http.api._apiServers[0]
1616
})
1717

1818
before(async function () {

test/http-api/inject/block.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = (http) => {
1313
let api
1414

1515
before(() => {
16-
api = http.api._apiServer
16+
api = http.api._apiServers[0]
1717
})
1818

1919
describe('/block/put', () => {

test/http-api/inject/bootstrap.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = (http) => {
1111
let api
1212

1313
before(() => {
14-
api = http.api._apiServer
14+
api = http.api._apiServers[0]
1515
return api.inject({
1616
method: 'GET',
1717
url: '/api/v0/bootstrap/add/default'

test/http-api/inject/config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module.exports = (http) => {
1717

1818
before(() => {
1919
updatedConfig = () => JSON.parse(fs.readFileSync(configPath, 'utf8'))
20-
api = http.api._apiServer
20+
api = http.api._apiServers[0]
2121
})
2222

2323
after(() => {

test/http-api/inject/dht.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = (http) => {
1212
let api
1313

1414
before(() => {
15-
api = http.api._apiServer
15+
api = http.api._apiServers[0]
1616
})
1717

1818
describe('/findpeer', () => {

test/http-api/inject/dns.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = (http) => {
88
let api
99

1010
before(() => {
11-
api = http.api._apiServer
11+
api = http.api._apiServers[0]
1212
})
1313

1414
it('resolve ipfs.io dns', async () => {

test/http-api/inject/files.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = (http) => {
1313
let api
1414

1515
before(() => {
16-
api = http.api._apiServer
16+
api = http.api._apiServers[0]
1717
})
1818

1919
describe('/add', () => {

test/http-api/inject/id.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = (http) => {
88
let api
99

1010
before(() => {
11-
api = http.api._apiServer
11+
api = http.api._apiServers[0]
1212
})
1313

1414
it('get the id', async () => {

test/http-api/inject/name.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = (http) => {
1616
let api
1717

1818
before(() => {
19-
api = http.api._apiServer
19+
api = http.api._apiServers[0]
2020
})
2121

2222
it('should publish a record', async function () {

test/http-api/inject/object.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module.exports = (http) => {
1717
let api
1818

1919
before('api', () => {
20-
api = http.api._apiServer
20+
api = http.api._apiServers[0]
2121
})
2222

2323
describe('/new', () => {

test/http-api/inject/pin.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module.exports = (http) => {
3737
let api
3838

3939
before(() => {
40-
api = http.api._apiServer
40+
api = http.api._apiServers[0]
4141
})
4242

4343
describe('rm', () => {

test/http-api/inject/ping.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = (http) => {
1313
let api
1414

1515
before(() => {
16-
api = http.api._apiServer
16+
api = http.api._apiServers[0]
1717
})
1818

1919
it('returns 400 if both n and count are provided', async () => {

test/http-api/inject/pubsub.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = (http) => {
1616
const topicNotSubscribed = 'somethingRandom'
1717

1818
before(() => {
19-
api = http.api._apiServer
19+
api = http.api._apiServers[0]
2020
})
2121

2222
describe('/sub', () => {

test/http-api/inject/resolve.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = (http) => {
1212
let api
1313

1414
before(() => {
15-
api = http.api._apiServer
15+
api = http.api._apiServers[0]
1616
})
1717

1818
it('should resolve a path and return a base2 encoded CID', async () => {

test/http-api/inject/version.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = (http) => {
99
let api
1010

1111
before(() => {
12-
api = http.api._apiServer
12+
api = http.api._apiServers[0]
1313
})
1414

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

0 commit comments

Comments
 (0)