mirror of
https://github.com/fluencelabs/js-multiaddr-to-uri
synced 2024-12-04 20:50:30 +00:00
feat: assume HTTP when multiaddr ends with /tcp (#7)
This makes multiaddrs ending with `/tcp/8080` to default to HTTP unless an explicit assumeHttp: false is passed. We also skip default ports for HTTP and HTTPS in the URL. Motivation: https://github.com/ipfs/js-ipfs/pull/2358#issue-307463029 License: MIT Signed-off-by: Marcin Rataj <lidel@lidel.org>
This commit is contained in:
parent
ad08d43abb
commit
adda9366c1
@ -18,10 +18,19 @@ const toUri = require('multiaddr-to-uri')
|
|||||||
|
|
||||||
console.log(toUri('/dnsaddr/protocol.ai/https'))
|
console.log(toUri('/dnsaddr/protocol.ai/https'))
|
||||||
// -> https://protocol.ai
|
// -> https://protocol.ai
|
||||||
|
|
||||||
|
console.log(toUri('/ip4/127.0.0.1/tcp/8080'))
|
||||||
|
// -> http://127.0.0.1:8080
|
||||||
|
|
||||||
|
console.log(toUri('/ip4/127.0.0.1/tcp/8080', { assumeHttp: false }))
|
||||||
|
// -> tcp://127.0.0.1:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
|
|
||||||
|
* When `/tcp` is the last (terminating) protocol HTTP is assumed by default (implicit `assumeHttp: true`)
|
||||||
|
* this means produced URIs will start with `http://` instead of `tcp://`
|
||||||
|
* passing `{ assumeHttp: false }` disables this behavior
|
||||||
* Might be lossy - e.g. a DNSv6 multiaddr
|
* Might be lossy - e.g. a DNSv6 multiaddr
|
||||||
* Can throw if the passed multiaddr:
|
* Can throw if the passed multiaddr:
|
||||||
* is not a valid multiaddr
|
* is not a valid multiaddr
|
||||||
|
23
index.js
23
index.js
@ -1,5 +1,20 @@
|
|||||||
const Multiaddr = require('multiaddr')
|
const Multiaddr = require('multiaddr')
|
||||||
|
|
||||||
const reduceValue = (_, v) => v
|
const reduceValue = (_, v) => v
|
||||||
|
const tcpUri = (str, port, parts, opts) => {
|
||||||
|
// return tcp when explicitly requested
|
||||||
|
if (opts && opts.assumeHttp === false) return `tcp://${str}:${port}`
|
||||||
|
// check if tcp is the last protocol in multiaddr
|
||||||
|
let protocol = 'tcp'
|
||||||
|
let explicitPort = `:${port}`
|
||||||
|
const last = parts[parts.length - 1]
|
||||||
|
if (last.protocol === 'tcp') {
|
||||||
|
// assume http and produce clean urls
|
||||||
|
protocol = port === 443 ? 'https' : 'http'
|
||||||
|
explicitPort = port === 443 || port === 80 ? '' : explicitPort
|
||||||
|
}
|
||||||
|
return `${protocol}://${str}${explicitPort}`
|
||||||
|
}
|
||||||
|
|
||||||
const Reducers = {
|
const Reducers = {
|
||||||
ip4: reduceValue,
|
ip4: reduceValue,
|
||||||
@ -8,10 +23,10 @@ const Reducers = {
|
|||||||
? content
|
? content
|
||||||
: `[${content}]`
|
: `[${content}]`
|
||||||
),
|
),
|
||||||
tcp: (str, content, i, parts) => (
|
tcp: (str, content, i, parts, opts) => (
|
||||||
parts.some(p => ['http', 'https', 'ws', 'wss'].includes(p.protocol))
|
parts.some(p => ['http', 'https', 'ws', 'wss'].includes(p.protocol))
|
||||||
? `${str}:${content}`
|
? `${str}:${content}`
|
||||||
: `tcp://${str}:${content}`
|
: tcpUri(str, content, parts, opts)
|
||||||
),
|
),
|
||||||
udp: (str, content) => `udp://${str}:${content}`,
|
udp: (str, content) => `udp://${str}:${content}`,
|
||||||
dnsaddr: reduceValue,
|
dnsaddr: reduceValue,
|
||||||
@ -28,7 +43,7 @@ const Reducers = {
|
|||||||
'p2p-webrtc-direct': str => `${str}/p2p-webrtc-direct`
|
'p2p-webrtc-direct': str => `${str}/p2p-webrtc-direct`
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (multiaddr) => (
|
module.exports = (multiaddr, opts) => (
|
||||||
Multiaddr(multiaddr)
|
Multiaddr(multiaddr)
|
||||||
.stringTuples()
|
.stringTuples()
|
||||||
.map(tuple => ({
|
.map(tuple => ({
|
||||||
@ -38,6 +53,6 @@ module.exports = (multiaddr) => (
|
|||||||
.reduce((str, part, i, parts) => {
|
.reduce((str, part, i, parts) => {
|
||||||
const reduce = Reducers[part.protocol]
|
const reduce = Reducers[part.protocol]
|
||||||
if (!reduce) throw new Error(`Unsupported protocol ${part.protocol}`)
|
if (!reduce) throw new Error(`Unsupported protocol ${part.protocol}`)
|
||||||
return reduce(str, part.content, i, parts)
|
return reduce(str, part.content, i, parts, opts)
|
||||||
}, '')
|
}, '')
|
||||||
)
|
)
|
||||||
|
39
test.js
39
test.js
@ -7,19 +7,14 @@ test('should convert multiaddr to URI', (t) => {
|
|||||||
['/ip4/127.0.0.1/http', 'http://127.0.0.1'],
|
['/ip4/127.0.0.1/http', 'http://127.0.0.1'],
|
||||||
['/ip6/fc00::', 'fc00::'],
|
['/ip6/fc00::', 'fc00::'],
|
||||||
['/ip6/fc00::/http', 'http://[fc00::]'],
|
['/ip6/fc00::/http', 'http://[fc00::]'],
|
||||||
['/ip4/0.0.7.6/tcp/1234', 'tcp://0.0.7.6:1234'],
|
|
||||||
['/ip4/0.0.7.6/tcp/1234/http', 'http://0.0.7.6:1234'],
|
['/ip4/0.0.7.6/tcp/1234/http', 'http://0.0.7.6:1234'],
|
||||||
['/ip4/0.0.7.6/tcp/1234/https', 'https://0.0.7.6:1234'],
|
['/ip4/0.0.7.6/tcp/1234/https', 'https://0.0.7.6:1234'],
|
||||||
['/ip6/::/tcp/0', 'tcp://[::]:0'],
|
|
||||||
['/ip4/0.0.7.6/udp/1234', 'udp://0.0.7.6:1234'],
|
['/ip4/0.0.7.6/udp/1234', 'udp://0.0.7.6:1234'],
|
||||||
['/ip6/::/udp/0', 'udp://[::]:0'],
|
['/ip6/::/udp/0', 'udp://[::]:0'],
|
||||||
['/dnsaddr/ipfs.io', 'ipfs.io'],
|
['/dnsaddr/ipfs.io', 'ipfs.io'],
|
||||||
['/dns4/ipfs.io', 'ipfs.io'],
|
['/dns4/ipfs.io', 'ipfs.io'],
|
||||||
['/dns4/libp2p.io', 'libp2p.io'],
|
['/dns4/libp2p.io', 'libp2p.io'],
|
||||||
['/dns6/protocol.ai', 'protocol.ai'],
|
['/dns6/protocol.ai', 'protocol.ai'],
|
||||||
['/dns4/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
|
||||||
['/dns6/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
|
||||||
['/dnsaddr/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
|
||||||
['/dnsaddr/protocol.ai/tcp/80/http', 'http://protocol.ai:80'],
|
['/dnsaddr/protocol.ai/tcp/80/http', 'http://protocol.ai:80'],
|
||||||
['/dnsaddr/protocol.ai/tcp/80/https', 'https://protocol.ai:80'],
|
['/dnsaddr/protocol.ai/tcp/80/https', 'https://protocol.ai:80'],
|
||||||
['/dnsaddr/ipfs.io/ws', 'ws://ipfs.io'],
|
['/dnsaddr/ipfs.io/ws', 'ws://ipfs.io'],
|
||||||
@ -83,6 +78,40 @@ test('should convert multiaddr to URI', (t) => {
|
|||||||
data.forEach(d => t.is(toUri(d[0]), d[1]))
|
data.forEach(d => t.is(toUri(d[0]), d[1]))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should convert multiaddr to http(s):// URI when implicit { assumeHttp: true }', (t) => {
|
||||||
|
const data = [
|
||||||
|
['/ip4/0.0.7.6/tcp/1234', 'http://0.0.7.6:1234'],
|
||||||
|
['/ip6/::/tcp/0', 'http://[::]:0'],
|
||||||
|
['/dns4/protocol.ai/tcp/80', 'http://protocol.ai'],
|
||||||
|
['/dns6/protocol.ai/tcp/80', 'http://protocol.ai'],
|
||||||
|
['/dns4/protocol.ai/tcp/8080', 'http://protocol.ai:8080'],
|
||||||
|
['/dns6/protocol.ai/tcp/8080', 'http://protocol.ai:8080'],
|
||||||
|
['/dns4/protocol.ai/tcp/443', 'https://protocol.ai'],
|
||||||
|
['/dns6/protocol.ai/tcp/443', 'https://protocol.ai'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/80', 'http://protocol.ai'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/443', 'https://protocol.ai'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/8080', 'http://protocol.ai:8080']
|
||||||
|
]
|
||||||
|
data.forEach(d => t.is(toUri(d[0]), d[1]))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should convert multiaddr to tcp:// URI when explicit { assumeHttp: false }', (t) => {
|
||||||
|
const data = [
|
||||||
|
['/ip4/0.0.7.6/tcp/1234', 'tcp://0.0.7.6:1234'],
|
||||||
|
['/ip6/::/tcp/0', 'tcp://[::]:0'],
|
||||||
|
['/dns4/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
||||||
|
['/dns6/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
||||||
|
['/dns4/protocol.ai/tcp/8080', 'tcp://protocol.ai:8080'],
|
||||||
|
['/dns6/protocol.ai/tcp/8080', 'tcp://protocol.ai:8080'],
|
||||||
|
['/dns4/protocol.ai/tcp/443', 'tcp://protocol.ai:443'],
|
||||||
|
['/dns6/protocol.ai/tcp/443', 'tcp://protocol.ai:443'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/80', 'tcp://protocol.ai:80'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/443', 'tcp://protocol.ai:443'],
|
||||||
|
['/dnsaddr/protocol.ai/tcp/8080', 'tcp://protocol.ai:8080']
|
||||||
|
]
|
||||||
|
data.forEach(d => t.is(toUri(d[0], { assumeHttp: false }), d[1]))
|
||||||
|
})
|
||||||
|
|
||||||
test('should throw for unsupported protocol', (t) => {
|
test('should throw for unsupported protocol', (t) => {
|
||||||
t.throws(() => toUri('/quic'))
|
t.throws(() => toUri('/quic'))
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user