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

Commit b554002

Browse files
test: add tests for different types of connection config (#3388)
We claim to support URLs, MultiAddrs, strings and individual URL components so add tests for them. Also, add code to actually support the above permutations.. Co-authored-by: Vasco Santos <[email protected]>
1 parent 583503b commit b554002

File tree

5 files changed

+134
-41
lines changed

5 files changed

+134
-41
lines changed

packages/ipfs-core-utils/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
"it-all": "^1.0.4",
4747
"it-map": "^1.0.4",
4848
"it-peekable": "^1.0.1",
49+
"multiaddr": "^8.0.0",
50+
"multiaddr-to-uri": "^6.0.0",
4951
"uint8arrays": "^1.1.0"
5052
},
5153
"devDependencies": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict'
2+
3+
const multiaddr = require('multiaddr')
4+
const multiAddrToUri = require('multiaddr-to-uri')
5+
6+
/**
7+
* @param {string|Multiaddr|URL} url - A string, multiaddr or URL to convert to a url string
8+
* @returns {string}
9+
*/
10+
module.exports = (url) => {
11+
try {
12+
// @ts-expect-error
13+
url = multiAddrToUri(multiaddr(url))
14+
} catch (err) { }
15+
16+
url = url.toString()
17+
18+
return url
19+
}
20+
21+
/**
22+
* @typedef {import('multiaddr')} Multiaddr
23+
*/

packages/ipfs-http-client/package.json

-2
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,13 @@
6161
"ipld-dag-cbor": "^0.17.0",
6262
"ipld-dag-pb": "^0.20.0",
6363
"ipld-raw": "^6.0.0",
64-
"iso-url": "^1.0.0",
6564
"it-last": "^1.0.4",
6665
"it-map": "^1.0.4",
6766
"it-tar": "^1.2.2",
6867
"it-to-buffer": "^1.0.2",
6968
"it-to-stream": "^0.1.2",
7069
"merge-options": "^2.0.0",
7170
"multiaddr": "^8.0.0",
72-
"multiaddr-to-uri": "^6.0.0",
7371
"multibase": "^3.0.0",
7472
"multicodec": "^2.0.1",
7573
"multihashes": "^3.0.1",

packages/ipfs-http-client/src/lib/core.js

+39-38
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,59 @@
11
'use strict'
22
/* eslint-env browser */
33
const Multiaddr = require('multiaddr')
4-
const toUri = require('multiaddr-to-uri')
54
const { isBrowser, isWebWorker } = require('ipfs-utils/src/env')
6-
const { URL } = require('iso-url')
75
const parseDuration = require('parse-duration').default
86
const log = require('debug')('ipfs-http-client:lib:error-handler')
97
const HTTP = require('ipfs-utils/src/http')
108
const merge = require('merge-options')
9+
const toUrlString = require('ipfs-core-utils/src/to-url-string')
1110

12-
/**
13-
* @param {any} input
14-
* @returns {input is Multiaddr}
15-
*/
16-
const isMultiaddr = (input) => {
17-
try {
18-
Multiaddr(input) // eslint-disable-line no-new
19-
return true
20-
} catch (e) {
21-
return false
22-
}
23-
}
11+
const DEFAULT_PROTOCOL = isBrowser || isWebWorker ? location.protocol : 'http'
12+
const DEFAULT_HOST = isBrowser || isWebWorker ? location.hostname : 'localhost'
13+
const DEFAULT_PORT = isBrowser || isWebWorker ? location.port : '5001'
2414

2515
/**
26-
* @param {any} options
16+
* @param {ClientOptions|URL|Multiaddr|string} [options]
2717
* @returns {ClientOptions}
2818
*/
29-
const normalizeInput = (options = {}) => {
30-
if (isMultiaddr(options)) {
31-
options = { url: toUri(options) }
32-
} else if (typeof options === 'string') {
33-
options = { url: options }
19+
const normalizeOptions = (options = {}) => {
20+
let url
21+
let opts = {}
22+
23+
if (typeof options === 'string' || Multiaddr.isMultiaddr(options)) {
24+
url = new URL(toUrlString(options))
25+
} else if (options instanceof URL) {
26+
url = options
27+
} else if (typeof options.url === 'string' || Multiaddr.isMultiaddr(options.url)) {
28+
url = new URL(toUrlString(options.url))
29+
opts = options
30+
} else if (options.url instanceof URL) {
31+
url = options.url
32+
opts = options
33+
} else {
34+
opts = options || {}
35+
36+
const protocol = (opts.protocol || DEFAULT_PROTOCOL).replace(':', '')
37+
const host = (opts.host || DEFAULT_HOST).split(':')[0]
38+
const port = (opts.port || DEFAULT_PORT)
39+
40+
url = new URL(`${protocol}://${host}:${port}`)
3441
}
3542

36-
const url = new URL(options.url)
37-
if (options.apiPath) {
38-
url.pathname = options.apiPath
43+
if (opts.apiPath) {
44+
url.pathname = opts.apiPath
3945
} else if (url.pathname === '/' || url.pathname === undefined) {
4046
url.pathname = 'api/v0'
4147
}
42-
if (!options.url) {
43-
if (isBrowser || isWebWorker) {
44-
url.protocol = options.protocol || location.protocol
45-
url.hostname = options.host || location.hostname
46-
url.port = options.port || location.port
47-
} else {
48-
url.hostname = options.host || 'localhost'
49-
url.port = options.port || '5001'
50-
url.protocol = options.protocol || 'http'
51-
}
52-
}
53-
options.url = url
5448

55-
return options
49+
return {
50+
...opts,
51+
host: url.host,
52+
protocol: url.protocol.replace(':', ''),
53+
port: Number(url.port),
54+
apiPath: url.pathname,
55+
url
56+
}
5657
}
5758

5859
const errorHandler = async (response) => {
@@ -111,7 +112,7 @@ const parseTimeout = (value) => {
111112
* @property {Headers|Record<string, string>} [headers] - Request headers.
112113
* @property {number|string} [timeout] - Amount of time until request should timeout in ms or humand readable. https://www.npmjs.com/package/parse-duration for valid string values.
113114
* @property {string} [apiPath] - Path to the API.
114-
* @property {URL|string} [url] - Full API URL.
115+
* @property {URL|string|Multiaddr} [url] - Full API URL.
115116
* @property {object} [ipld]
116117
* @property {any[]} [ipld.formats] - An array of additional [IPLD formats](https://github.com/ipld/interface-ipld-format) to support
117118
* @property {(format: string) => Promise<any>} [ipld.loadFormat] - an async function that takes the name of an [IPLD format](https://github.com/ipld/interface-ipld-format) as a string and should return the implementation of that codec
@@ -121,7 +122,7 @@ class Client extends HTTP {
121122
* @param {ClientOptions|URL|Multiaddr|string} [options]
122123
*/
123124
constructor (options = {}) {
124-
const opts = normalizeInput(options)
125+
const opts = normalizeOptions(options)
125126

126127
super({
127128
timeout: parseTimeout(opts.timeout) || 60000 * 20,

packages/ipfs-http-client/test/constructor.spec.js

+70-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ describe('ipfs-http-client constructor tests', () => {
2828
expectConfig(ipfs, { host, port, protocol })
2929
})
3030

31+
it('opts with URL components from URL', () => {
32+
const host = 'wizard.world'
33+
const port = '999'
34+
const protocol = 'https'
35+
const url = new URL(`${protocol}://${host}:${port}`)
36+
const ipfs = ipfsClient({ host: url.host, port: url.port, protocol: url.protocol })
37+
expectConfig(ipfs, { host, port, protocol })
38+
})
39+
3140
it('multiaddr dns4 string (implicit http)', () => {
3241
const host = 'foo.com'
3342
const port = '1001'
@@ -79,6 +88,22 @@ describe('ipfs-http-client constructor tests', () => {
7988
expectConfig(ipfs, { host, port })
8089
})
8190

91+
it('URL as string', () => {
92+
const host = '10.100.100.255'
93+
const port = '9999'
94+
const apiPath = '/future/api/v1/'
95+
const ipfs = ipfsClient(`http://${host}:${port}${apiPath}`)
96+
expectConfig(ipfs, { host, port, apiPath })
97+
})
98+
99+
it('URL as URL', () => {
100+
const host = '10.100.100.255'
101+
const port = '9999'
102+
const apiPath = '/future/api/v1/'
103+
const ipfs = ipfsClient(new URL(`http://${host}:${port}${apiPath}`))
104+
expectConfig(ipfs, { host, port, apiPath })
105+
})
106+
82107
it('host, port and api path', () => {
83108
const host = '10.100.100.255'
84109
const port = '9999'
@@ -87,13 +112,57 @@ describe('ipfs-http-client constructor tests', () => {
87112
expectConfig(ipfs, { host, port, apiPath })
88113
})
89114

90-
it('url', () => {
115+
it('options.url as URL string', () => {
91116
const host = '10.100.100.255'
92117
const port = '9999'
93118
const apiPath = '/future/api/v1/'
94119
const ipfs = ipfsClient({ url: `http://${host}:${port}${apiPath}` })
95120
expectConfig(ipfs, { host, port, apiPath })
96121
})
122+
123+
it('options.url as URL', () => {
124+
const host = '10.100.100.255'
125+
const port = '9999'
126+
const apiPath = '/future/api/v1/'
127+
const ipfs = ipfsClient({ url: new URL(`http://${host}:${port}${apiPath}`) })
128+
expectConfig(ipfs, { host, port, apiPath })
129+
})
130+
131+
it('options.url as multiaddr (implicit http)', () => {
132+
const host = 'foo.com'
133+
const port = '1001'
134+
const protocol = 'http' // default to http if not specified in multiaddr
135+
const addr = `/dns4/${host}/tcp/${port}`
136+
const ipfs = ipfsClient({ url: multiaddr(addr) })
137+
expectConfig(ipfs, { host, port, protocol })
138+
})
139+
140+
it('options.url as multiaddr (explicit https)', () => {
141+
const host = 'foo.com'
142+
const port = '1001'
143+
const protocol = 'https'
144+
const addr = `/dns4/${host}/tcp/${port}/https`
145+
const ipfs = ipfsClient({ url: multiaddr(addr) })
146+
expectConfig(ipfs, { host, port, protocol })
147+
})
148+
149+
it('options.url as multiaddr string (implicit http)', () => {
150+
const host = 'foo.com'
151+
const port = '1001'
152+
const protocol = 'http' // default to http if not specified in multiaddr
153+
const addr = `/dns4/${host}/tcp/${port}`
154+
const ipfs = ipfsClient({ url: addr })
155+
expectConfig(ipfs, { host, port, protocol })
156+
})
157+
158+
it('options.url as multiaddr string (explicit https)', () => {
159+
const host = 'foo.com'
160+
const port = '1001'
161+
const protocol = 'https'
162+
const addr = `/dns4/${host}/tcp/${port}/https`
163+
const ipfs = ipfsClient({ url: addr })
164+
expectConfig(ipfs, { host, port, protocol })
165+
})
97166
})
98167

99168
describe('integration', () => {

0 commit comments

Comments
 (0)