From e4dad1341414b158a86ac8a26582f875082c7eca Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 5 Nov 2020 17:48:13 +0000 Subject: [PATCH 1/7] feat: expose gRPC addr on daemon Adds a `grpcAddr` property to IPFS daemon instances that contains the multiaddr of the gPRC websocket server exposed if available. --- src/ipfsd-daemon.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index 79347468..fe165dc0 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -48,6 +48,7 @@ class Daemon { this.started = false this.clean = true this.apiAddr = null + this.grpcAddr = null this.gatewayAddr = null this.api = null } @@ -63,6 +64,14 @@ class Daemon { this.api.apiPort = this.apiAddr.nodeAddress().port } + /** + * @private + * @param {string} addr + */ + _setGRPC (addr) { + this.grpcAddr = multiaddr(addr) + } + /** * @private * @param {string} addr @@ -168,6 +177,7 @@ class Daemon { output += data.toString() const apiMatch = output.trim().match(/API .*listening on:? (.*)/) const gwMatch = output.trim().match(/Gateway .*listening on:? (.*)/) + const grpcMatch = output.trim().match(/gRPC .*listening on:? (.*)/) if (apiMatch && apiMatch.length > 0) { this._setApi(apiMatch[1]) @@ -177,6 +187,10 @@ class Daemon { this._setGateway(gwMatch[1]) } + if (grpcMatch && grpcMatch.length > 0) { + this._setGRPC(grpcMatch[1]) + } + if (output.match(/(?:daemon is running|Daemon is ready)/)) { // we're good this.started = true From 1c01938f0e8e5293ef726b08560e425dcd6ecbbc Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 10 Nov 2020 16:18:14 +0000 Subject: [PATCH 2/7] feat: accept ipfsClientModule as argument --- src/ipfsd-client.js | 42 +++++++++++++++++++++++++++++++++++--- src/ipfsd-daemon.js | 36 ++++++++++++++++++++++++++------- test/create.spec.js | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 10 deletions(-) diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index 1e94762a..62579373 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -37,6 +37,8 @@ class Client { this._setApi(remoteState.apiAddr) this._setGateway(remoteState.gatewayAddr) + this._setGrpc(remoteState.grpcAddr) + this._createApi() } /** @@ -46,9 +48,6 @@ class Client { _setApi (addr) { if (addr) { this.apiAddr = multiaddr(addr) - this.api = this.opts.ipfsHttpModule(addr) - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port } } @@ -59,9 +58,46 @@ class Client { _setGateway (addr) { if (addr) { this.gatewayAddr = multiaddr(addr) + } + } + + /** + * @private + * @param {string} addr + */ + _setGrpc (addr) { + if (addr) { + this.grpcAddr = multiaddr(addr) + } + } + + /** + * @private + */ + _createApi () { + if (this.opts.ipfsClientModule && this.grpcAddr) { + this.api = this.opts.ipfsClientModule({ + grpc: this.grpcAddr, + http: this.apiAddr + }) + } else { + this.api = this.opts.ipfsHttpModule(addr) + } + + if (this.apiAddr) { + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } + + if (this.gatewayAddr) { this.api.gatewayHost = this.gatewayAddr.nodeAddress().address this.api.gatewayPort = this.gatewayAddr.nodeAddress().port } + + if (this.grpcAddr) { + this.api.grpcHost = this.grpcAddr.nodeAddress().address + this.api.grpcPort = this.grpcAddr.nodeAddress().port + } } /** diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index fe165dc0..1fe9507f 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -59,16 +59,13 @@ class Daemon { */ _setApi (addr) { this.apiAddr = multiaddr(addr) - this.api = this.opts.ipfsHttpModule(addr) - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port } /** * @private * @param {string} addr */ - _setGRPC (addr) { + _setGrpc (addr) { this.grpcAddr = multiaddr(addr) } @@ -78,8 +75,32 @@ class Daemon { */ _setGateway (addr) { this.gatewayAddr = multiaddr(addr) - this.api.gatewayHost = this.gatewayAddr.nodeAddress().address - this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + _createApi () { + if (this.opts.ipfsClientModule && this.grpcAddr) { + this.api = this.opts.ipfsClientModule({ + grpc: this.grpcAddr, + http: this.apiAddr + }) + } else { + this.api = this.opts.ipfsHttpModule(addr) + } + + if (this.apiAddr) { + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } + + if (this.gatewayAddr) { + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + if (this.grpcAddr) { + this.api.grpcHost = this.grpcAddr.nodeAddress().address + this.api.grpcPort = this.grpcAddr.nodeAddress().port + } } /** @@ -188,11 +209,12 @@ class Daemon { } if (grpcMatch && grpcMatch.length > 0) { - this._setGRPC(grpcMatch[1]) + this._setGrpc(grpcMatch[1]) } if (output.match(/(?:daemon is running|Daemon is ready)/)) { // we're good + this._createApi() this.started = true this.subprocess.stdout.off('data', readyHandler) resolve(this.api) diff --git a/test/create.spec.js b/test/create.spec.js index f9349da1..08d21da9 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -56,6 +56,55 @@ describe('`createController` should return the correct class', () => { expect(f).to.be.instanceOf(Client) }) + + it.skip('should use ipfs-client if passed', async () => { + let clientCreated = false + let httpCreated = false + + const f = await createController({ + type: 'js', + disposable: false, + ipfsModule: require('ipfs'), + ipfsClientModule: (opts) => { + clientCreated = true + + return require('ipfs-client')(opts) + }, + ipfsHttpModule: (opts) => { + httpCreated = true + + return require('ipfs-http-client')(opts) + }, + ipfsBin: pathJoin(__dirname, '../node_modules/ipfs/src/cli/bin.js') + }) + + expect(clientCreated).to.be.true() + expect(httpCreated).to.be.false() + }) + + it.skip('should use ipfs-client for remote if passed', async () => { + let clientCreated = false + let httpCreated = false + + const f = await createController({ + remote: true, + disposable: false, + ipfsModule: require('ipfs'), + ipfsClientModule: (opts) => { + clientCreated = true + + return require('ipfs-client')(opts) + }, + ipfsHttpModule: (opts) => { + httpCreated = true + + return require('ipfs-http-client')(opts) + }, + ipfsBin: pathJoin(__dirname, '../node_modules/ipfs/src/cli/bin.js') + }) + + expect(f).to.be.instanceOf(Client) + }) }) const defaultOps = { From 3e5387af9bc674b8a8e8f64acf522514f91298af Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 10 Nov 2020 16:58:37 +0000 Subject: [PATCH 3/7] chore: update addr var and return grpcAddr in remote response --- src/endpoint/routes.js | 1 + src/ipfsd-client.js | 2 +- src/ipfsd-daemon.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/endpoint/routes.js b/src/endpoint/routes.js index cd909c51..c333542a 100644 --- a/src/endpoint/routes.js +++ b/src/endpoint/routes.js @@ -75,6 +75,7 @@ module.exports = (server, createFactory) => { id: id, apiAddr: nodes[id].apiAddr ? nodes[id].apiAddr.toString() : '', gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '', + grpcAddr: nodes[id].grpcAddr ? nodes[id].grpcAddr.toString() : '', initialized: nodes[id].initialized, started: nodes[id].started, disposable: nodes[id].disposable, diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index 62579373..b603aa61 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -81,7 +81,7 @@ class Client { http: this.apiAddr }) } else { - this.api = this.opts.ipfsHttpModule(addr) + this.api = this.opts.ipfsHttpModule(this.apiAddr) } if (this.apiAddr) { diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index 1fe9507f..ce95c119 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -84,7 +84,7 @@ class Daemon { http: this.apiAddr }) } else { - this.api = this.opts.ipfsHttpModule(addr) + this.api = this.opts.ipfsHttpModule(this.apiAddr) } if (this.apiAddr) { From f070c649ff904cc4c706150689018d172babce02 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 10 Nov 2020 17:57:14 +0000 Subject: [PATCH 4/7] fix: make rpc listen on random free port --- src/config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.js b/src/config.js index b5c9aa31..da3fd550 100644 --- a/src/config.js +++ b/src/config.js @@ -29,7 +29,8 @@ module.exports = ({ type }) => { Addresses: { Swarm: swarm, API: '/ip4/127.0.0.1/tcp/0', - Gateway: '/ip4/127.0.0.1/tcp/0' + Gateway: '/ip4/127.0.0.1/tcp/0', + RPC: '/ip4/127.0.0.1/tcp/0' } } } From 020ccf34502a4285f17321a83116e3069bcccf6a Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 12 Nov 2020 10:49:06 +0000 Subject: [PATCH 5/7] chore: create api on start --- src/endpoint/routes.js | 3 ++- src/ipfsd-client.js | 34 +++++++++++++++++++--------------- test/create.spec.js | 4 +++- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/endpoint/routes.js b/src/endpoint/routes.js index c333542a..f12d54f3 100644 --- a/src/endpoint/routes.js +++ b/src/endpoint/routes.js @@ -126,7 +126,8 @@ module.exports = (server, createFactory) => { return { apiAddr: nodes[id].apiAddr ? nodes[id].apiAddr.toString() : '', - gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '' + gatewayAddr: nodes[id].gatewayAddr ? nodes[id].gatewayAddr.toString() : '', + grpcAddr: nodes[id].grpcAddr ? nodes[id].grpcAddr.toString() : '' } } catch (err) { badRequest(err) diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index b603aa61..40a14dc1 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -75,28 +75,30 @@ class Client { * @private */ _createApi () { - if (this.opts.ipfsClientModule && this.grpcAddr) { + if (this.opts.ipfsClientModule && this.grpcAddr && this.apiAddr) { this.api = this.opts.ipfsClientModule({ grpc: this.grpcAddr, http: this.apiAddr }) - } else { + } else if (this.apiAddr) { this.api = this.opts.ipfsHttpModule(this.apiAddr) } - if (this.apiAddr) { - this.api.apiHost = this.apiAddr.nodeAddress().address - this.api.apiPort = this.apiAddr.nodeAddress().port - } - - if (this.gatewayAddr) { - this.api.gatewayHost = this.gatewayAddr.nodeAddress().address - this.api.gatewayPort = this.gatewayAddr.nodeAddress().port - } - - if (this.grpcAddr) { - this.api.grpcHost = this.grpcAddr.nodeAddress().address - this.api.grpcPort = this.grpcAddr.nodeAddress().port + if (this.api) { + if (this.apiAddr) { + this.api.apiHost = this.apiAddr.nodeAddress().address + this.api.apiPort = this.apiAddr.nodeAddress().port + } + + if (this.gatewayAddr) { + this.api.gatewayHost = this.gatewayAddr.nodeAddress().address + this.api.gatewayPort = this.gatewayAddr.nodeAddress().port + } + + if (this.grpcAddr) { + this.api.grpcHost = this.grpcAddr.nodeAddress().address + this.api.grpcPort = this.grpcAddr.nodeAddress().port + } } } @@ -169,6 +171,8 @@ class Client { this._setApi(res.apiAddr) this._setGateway(res.gatewayAddr) + this._setGrpc(res.grpcAddr) + this._createApi() this.started = true } diff --git a/test/create.spec.js b/test/create.spec.js index 08d21da9..a52b0834 100644 --- a/test/create.spec.js +++ b/test/create.spec.js @@ -61,7 +61,7 @@ describe('`createController` should return the correct class', () => { let clientCreated = false let httpCreated = false - const f = await createController({ + await createController({ type: 'js', disposable: false, ipfsModule: require('ipfs'), @@ -104,6 +104,8 @@ describe('`createController` should return the correct class', () => { }) expect(f).to.be.instanceOf(Client) + expect(clientCreated).to.be.true() + expect(httpCreated).to.be.false() }) }) From a18066c38d86b930f0d241a535d1791cd3ea8cd9 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 12 Nov 2020 13:53:31 +0000 Subject: [PATCH 6/7] chore: update deps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 42de7456..46984083 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "peerDependencies": { "go-ipfs": "*", "ipfs": "*", + "ipfs-client": "*", "ipfs-http-client": "*" }, "repository": { From 254720c3f147417ddfa24cc9086a81bb04179f93 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 17 Nov 2020 09:26:17 +0000 Subject: [PATCH 7/7] chore: create api from multiaddr --- src/ipfsd-daemon.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index ce95c119..37ad558e 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -83,10 +83,14 @@ class Daemon { grpc: this.grpcAddr, http: this.apiAddr }) - } else { + } else if (this.apiAddr) { this.api = this.opts.ipfsHttpModule(this.apiAddr) } + if (!this.api) { + throw new Error(`Could not create API from http '${this.apiAddr}' and/or gRPC '${this.grpcAddr}'`) + } + if (this.apiAddr) { this.api.apiHost = this.apiAddr.nodeAddress().address this.api.apiPort = this.apiAddr.nodeAddress().port @@ -180,6 +184,7 @@ class Daemon { if (api) { this._setApi(api) + this._createApi() } else if (!this.exec) { throw new Error('No executable specified') } else {