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

Commit c5f0bc5

Browse files
authored
feat: allow passing a http.Agent to the grpc client (#3477)
Follows on from #3474 and allows using http.Agents with node.js to control the behaviour of the underlying node http client.
1 parent fe93ba0 commit c5f0bc5

File tree

29 files changed

+123
-27
lines changed

29 files changed

+123
-27
lines changed

examples/custom-ipld-formats/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"test-ipfs-example": "^2.0.3"
1212
},
1313
"dependencies": {
14-
"cids": "^1.0.0",
14+
"cids": "^1.1.5",
1515
"ipfs-daemon": "^0.3.1",
1616
"ipfs-core": "^0.3.0",
1717
"ipfs-http-client": "^48.1.2",

examples/traverse-ipld-graphs/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"test-ipfs-example": "^2.0.3"
1414
},
1515
"dependencies": {
16-
"cids": "^1.0.0",
16+
"cids": "^1.1.5",
1717
"ipfs": "^0.52.2",
1818
"ipld-block": "^0.11.0",
1919
"ipld-dag-pb": "^0.20.0",

packages/interface-ipfs-core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"chai": "^4.2.0",
3535
"chai-as-promised": "^7.1.1",
3636
"chai-subset": "^1.6.0",
37-
"cids": "^1.0.0",
37+
"cids": "^1.1.5",
3838
"delay": "^4.4.0",
3939
"dirty-chai": "^2.0.1",
4040
"err-code": "^2.0.3",

packages/ipfs-cli/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"bignumber.js": "^9.0.0",
3333
"byteman": "^1.3.5",
3434
"cid-tool": "^1.0.0",
35-
"cids": "^1.0.0",
35+
"cids": "^1.1.5",
3636
"debug": "^4.1.1",
3737
"err-code": "^2.0.3",
3838
"execa": "^5.0.0",

packages/ipfs-client/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ An optional object which may have the following keys:
2828
| ---- | ---- | ------- | ----------- |
2929
| grpc | `Multiaddr` or `string` or `URL` | `undefined` | The address of a [ipfs-grpc-server][] to connect to |
3030
| http | `Multiaddr` or `string` or `URL` | `undefined` | The address of a [ipfs-http-server][] to connect to |
31+
| agent | [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) | `undefined` | A http.Agent used to control HTTP client behaviour (node.js only) |
3132

3233
### Returns
3334

packages/ipfs-core-types/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
],
3030
"license": "(Apache-2.0 OR MIT)",
3131
"dependencies": {
32-
"cids": "^1.0.0",
32+
"cids": "^1.1.5",
3333
"multiaddr": "^8.0.0",
3434
"peer-id": "^0.14.1"
3535
},

packages/ipfs-core-utils/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"any-signal": "^2.0.0",
4242
"blob-to-it": "^1.0.1",
4343
"browser-readablestream-to-it": "^1.0.1",
44-
"cids": "^1.0.0",
44+
"cids": "^1.1.5",
4545
"err-code": "^2.0.3",
4646
"ipfs-utils": "^5.0.0",
4747
"ipfs-core-types": "^0.1.0",

packages/ipfs-core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"array-shuffle": "^1.0.1",
5858
"bignumber.js": "^9.0.0",
5959
"cbor": "^5.1.0",
60-
"cids": "^1.0.0",
60+
"cids": "^1.1.5",
6161
"class-is": "^1.1.0",
6262
"dag-cbor-links": "^2.0.0",
6363
"datastore-core": "^2.0.0",

packages/ipfs-grpc-client/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ An optional object which may have the following keys:
3535
| Name | Type | Default | Description |
3636
| ---- | ---- | ------- | ----------- |
3737
| url | `Multiaddr` or `string` or `URL` | `undefined` | The address of a [ipfs-grpc-server][] to connect to |
38+
| agent | [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) | `undefined` | A http.Agent used to control HTTP client behaviour (node.js only) |
3839

3940
### Returns
4041

packages/ipfs-grpc-client/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"dependencies": {
4343
"@improbable-eng/grpc-web": "^0.13.0",
4444
"change-case": "^4.1.1",
45-
"cids": "^1.0.0",
45+
"cids": "^1.1.5",
4646
"debug": "^4.1.1",
4747
"err-code": "^2.0.3",
4848
"ipfs-core-utils": "^0.5.0",

packages/ipfs-grpc-client/src/core-api/add-all.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ module.exports = function grpcAddAll (grpc, service, opts = {}) {
7979
} = bidiToDuplex(grpc, service, {
8080
host: opts.url,
8181
debug: Boolean(process.env.DEBUG),
82-
metadata: options
82+
metadata: options,
83+
agent: opts.agent
8384
})
8485

8586
sendFiles(stream, sink)

packages/ipfs-grpc-client/src/core-api/files/ls.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ module.exports = function grpcMfsLs (grpc, service, opts = {}) {
1313
for await (const result of serverStreamToIterator(grpc, service, request, {
1414
host: opts.url,
1515
debug: Boolean(process.env.DEBUG),
16-
metadata: options
16+
metadata: options,
17+
agent: opts.agent
1718
})) {
1819
yield {
1920
name: result.name,

packages/ipfs-grpc-client/src/core-api/files/write.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ module.exports = function grpcMfsWrite (grpc, service, opts = {}) {
3838
await clientStreamToPromise(grpc, service, stream(path, content), {
3939
host: opts.url,
4040
debug: Boolean(process.env.DEBUG),
41-
metadata: options
41+
metadata: options,
42+
agent: opts.agent
4243
})
4344
}
4445

packages/ipfs-grpc-client/src/core-api/id.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ module.exports = function grpcId (grpc, service, opts = {}) {
1111

1212
const res = await unaryToPromise(grpc, service, request, {
1313
host: opts.url,
14-
metadata: toHeaders(options)
14+
metadata: toHeaders(options),
15+
agent: opts.agent
1516
})
1617

1718
return {

packages/ipfs-grpc-client/src/grpc/transport.node.js

+26-5
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,32 @@ const WebsocketSignal = {
1313

1414
const finishSendFrame = new Uint8Array([1])
1515

16-
function WebsocketTransport () {
17-
return (opts) => {
18-
return websocketRequest(opts)
16+
/**
17+
* @param {object} options
18+
* @param {import('http').Agent} [options.agent] - http.Agent used to control HTTP client behaviour
19+
*/
20+
function WebsocketTransport (options) {
21+
/**
22+
* @param {import('@improbable-eng/grpc-web').grpc.TransportOptions} opts
23+
*/
24+
const websocketTransportFactory = (opts) => {
25+
return websocketRequest({
26+
...options,
27+
...opts
28+
})
1929
}
30+
31+
return websocketTransportFactory
2032
}
2133

34+
/**
35+
* @typedef {object} NodeTransportOptions
36+
* @property {import('http').Agent} [options.agent]
37+
*
38+
* @typedef {NodeTransportOptions & import('@improbable-eng/grpc-web').grpc.TransportOptions} WebSocketTransportOptions
39+
*
40+
* @param {WebSocketTransportOptions} options
41+
*/
2242
function websocketRequest (options) {
2343
const webSocketAddress = constructWebSocketAddress(options.url)
2444

@@ -54,7 +74,7 @@ function websocketRequest (options) {
5474
}
5575
},
5676
start: (metadata) => {
57-
ws = new WebSocket(webSocketAddress, ['grpc-websockets'])
77+
ws = new WebSocket(webSocketAddress, ['grpc-websockets'], options)
5878
ws.binaryType = 'arraybuffer'
5979
ws.onopen = function () {
6080
options.debug && debug('websocketRequest.onopen')
@@ -93,7 +113,8 @@ function constructWebSocketAddress (url) {
93113
} else if (url.substr(0, 7) === 'http://') {
94114
return `ws://${url.substr(7)}`
95115
}
96-
throw new Error('Websocket transport constructed with non-https:// or http:// host.')
116+
117+
throw new Error('Websocket transport url must start with ws:// or wss:// or http:// or https://')
97118
}
98119

99120
function headersToBytes (headers) {

packages/ipfs-grpc-client/src/index.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
'use strict'
22

3-
const transport = require('./grpc/transport')
43
const toUrlString = require('ipfs-core-utils/src/to-url-string')
54
const loadServices = require('./utils/load-services')
65
const { grpc } = require('@improbable-eng/grpc-web')
7-
grpc.setDefaultTransport(transport())
86

97
const service = loadServices()
108

@@ -21,7 +19,12 @@ function normaliseUrls (opts) {
2119
})
2220
}
2321

24-
module.exports = function createClient (opts = {}) {
22+
/**
23+
* @param {object} opts
24+
* @param {string} opts.url - The URL to connect to as a URL or Multiaddr
25+
* @param {import('http').Agent} [opts.agent] - http.Agent used to control HTTP client behaviour (node.js only)
26+
*/
27+
module.exports = function createClient (opts = { url: '' }) {
2528
opts.url = toUrlString(opts.url)
2629

2730
// @improbable-eng/grpc-web requires http:// protocol URLs, not ws://

packages/ipfs-grpc-client/src/utils/bidi-to-duplex.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const pushable = require('it-pushable')
44
const errCode = require('err-code')
55
const toHeaders = require('./to-headers')
6+
const transport = require('../grpc/transport')
67

78
async function sendMessages (service, client, source) {
89
for await (const obj of source) {
@@ -23,6 +24,7 @@ async function sendMessages (service, client, source) {
2324
* @param {string} options.host - The remote host
2425
* @param {boolean} [options.debug] - Whether to print debug messages
2526
* @param {object} [options.metadata] - Metadata sent as headers
27+
* @param {import('http').Agent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only)
2628
* @returns {{ source: AsyncIterable<object>, sink: { push: Function, end: Function } }}
2729
**/
2830
module.exports = function bidiToDuplex (grpc, service, options) {
@@ -32,7 +34,12 @@ module.exports = function bidiToDuplex (grpc, service, options) {
3234
// @ts-ignore
3335
const sink = pushable()
3436

35-
const client = grpc.client(service, options)
37+
const client = grpc.client(service, {
38+
...options,
39+
transport: transport({
40+
agent: options.agent
41+
})
42+
})
3643
client.onMessage(message => {
3744
sink.push(message)
3845
})

packages/ipfs-grpc-client/src/utils/client-stream-to-promise.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const bidiToDuplex = require('./bidi-to-duplex')
1515
* @param {string} options.host - The remote host
1616
* @param {boolean} [options.debug] - Whether to print debug messages
1717
* @param {object} [options.metadata] - Metadata sent as headers
18+
* @param {import('http').Agent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only)
1819
* @returns {Promise<Object>} - A promise that resolves to a response object
1920
**/
2021
module.exports = async function clientStreamToPromise (grpc, service, source, options) {

packages/ipfs-grpc-client/src/utils/server-stream-to-iterator.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const bidiToDuplex = require('./bidi-to-duplex')
1414
* @param {string} options.host - The remote host
1515
* @param {boolean} [options.debug] - Whether to print debug messages
1616
* @param {object} [options.metadata] - Metadata sent as headers
17+
* @param {import('http').Agent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only)
1718
* @returns {AsyncIterable<object>}
1819
**/
1920
module.exports = function serverStreamToIterator (grpc, service, request, options) {

packages/ipfs-grpc-client/src/utils/unary-to-promise.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const bidiToDuplex = require('./bidi-to-duplex')
1515
* @param {string} options.host - The remote host
1616
* @param {boolean} [options.debug] - Whether to print debug messages
1717
* @param {object} [options.metadata] - Metadata sent as headers
18+
* @param {import('http').Agent} [options.agent] - http.Agent used to control HTTP client behaviour (node.js only)
1819
* @returns {Promise<Object>} - A promise that resolves to a response object
1920
**/
2021
module.exports = function unaryToPromise (grpc, service, request, options) {
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const grpcClient = require('../src')
5+
const WebSocket = require('ws')
6+
7+
function startServer () {
8+
return new Promise((resolve) => {
9+
const wss = new WebSocket.Server({ port: 0 })
10+
11+
wss.on('listening', () => {
12+
resolve({
13+
port: wss.address().port,
14+
close: () => wss.close()
15+
})
16+
})
17+
18+
wss.on('connection', (ws) => {
19+
ws.once('message', () => {
20+
ws.send('')
21+
ws.end()
22+
})
23+
})
24+
})
25+
}
26+
27+
describe('agent', function () {
28+
it('uses the passed agent', async () => {
29+
const server = await startServer()
30+
31+
try {
32+
await new Promise((resolve) => {
33+
const ipfs = grpcClient({
34+
url: `http://localhost:${server.port}`,
35+
agent: {
36+
addRequest () {
37+
// an agent method was invoked
38+
resolve()
39+
}
40+
}
41+
})
42+
43+
ipfs.id().catch(() => {})
44+
})
45+
} finally {
46+
server.close()
47+
}
48+
})
49+
})
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict'
2+
3+
require('./agent')

packages/ipfs-http-client/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"dependencies": {
5454
"any-signal": "^2.0.0",
5555
"bignumber.js": "^9.0.0",
56-
"cids": "^1.0.0",
56+
"cids": "^1.1.5",
5757
"debug": "^4.1.1",
5858
"form-data": "^3.0.0",
5959
"ipfs-core-utils": "^0.5.4",

packages/ipfs-http-client/src/dag/put.js

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ module.exports = configure((api, opts) => {
2828
const cid = new CID(options.cid)
2929
encodingOptions = {
3030
...options,
31-
// @ts-expect-error - https://github.com/multiformats/js-cid/pull/138
3231
format: multicodec.getName(cid.code),
3332
hashAlg: multihash.decode(cid.multihash).name
3433
}

packages/ipfs-http-client/test/node/agent.js

+5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ describe('agent', function () {
8282

8383
break
8484
}
85+
86+
if (i === 4) {
87+
// should have first two responses by now
88+
expect(responses).to.have.lengthOf(2)
89+
}
8590
}
8691

8792
// wait for the final request to arrive

packages/ipfs-http-gateway/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@hapi/ammo": "^5.0.1",
3333
"@hapi/boom": "^9.1.0",
3434
"@hapi/hapi": "^20.0.0",
35-
"cids": "^1.0.0",
35+
"cids": "^1.1.5",
3636
"debug": "^4.1.1",
3737
"hapi-pino": "^8.3.0",
3838
"ipfs-core-utils": "^0.5.4",

packages/ipfs-http-server/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@hapi/boom": "^9.1.0",
3333
"@hapi/content": "^5.0.2",
3434
"@hapi/hapi": "^20.0.0",
35-
"cids": "^1.0.0",
35+
"cids": "^1.1.5",
3636
"debug": "^4.1.1",
3737
"dlv": "^1.1.3",
3838
"err-code": "^2.0.3",

packages/ipfs-message-port-protocol/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"dep-check": "aegir dep-check -i typescript -i rimraf"
4343
},
4444
"dependencies": {
45-
"cids": "^1.0.0",
45+
"cids": "^1.1.5",
4646
"ipld-block": "^0.11.0"
4747
},
4848
"devDependencies": {

packages/ipfs-message-port-server/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"devDependencies": {
5151
"@types/it-all": "^1.0.0",
5252
"aegir": "^29.2.2",
53-
"cids": "^1.0.0",
53+
"cids": "^1.1.5",
5454
"ipfs-utils": "^5.0.0",
5555
"rimraf": "^3.0.2",
5656
"typescript": "4.0.x"

0 commit comments

Comments
 (0)